aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/core/jack.c71
-rw-r--r--sound/soc/atmel/atmel-pcm.c16
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c6
-rw-r--r--sound/soc/blackfin/Kconfig9
-rw-r--r--sound/soc/blackfin/Makefile4
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c (renamed from sound/soc/blackfin/bf5xx-ad1938.c)66
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h28
-rw-r--r--sound/soc/codecs/Kconfig12
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ad1938.c521
-rw-r--r--sound/soc/codecs/ad1938.h100
-rw-r--r--sound/soc/codecs/ad193x.c558
-rw-r--r--sound/soc/codecs/ad193x.h81
-rw-r--r--sound/soc/codecs/cq93vc.c298
-rw-r--r--sound/soc/codecs/cq93vc.h29
-rw-r--r--sound/soc/codecs/da7210.c153
-rw-r--r--sound/soc/codecs/ssm2602.c4
-rw-r--r--sound/soc/codecs/tlv320dac33.c38
-rw-r--r--sound/soc/codecs/twl4030.c72
-rwxr-xr-xsound/soc/codecs/twl6040.c1227
-rw-r--r--sound/soc/codecs/twl6040.h141
-rw-r--r--sound/soc/codecs/wm8350.c74
-rw-r--r--sound/soc/codecs/wm8350.h3
-rw-r--r--sound/soc/codecs/wm8750.c53
-rw-r--r--sound/soc/codecs/wm8903.c202
-rw-r--r--sound/soc/codecs/wm8903.h221
-rw-r--r--sound/soc/codecs/wm8904.c17
-rw-r--r--sound/soc/codecs/wm8904.h97
-rw-r--r--sound/soc/codecs/wm8960.c209
-rw-r--r--sound/soc/codecs/wm8960.h10
-rw-r--r--sound/soc/davinci/Kconfig27
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-evm.c61
-rw-r--r--sound/soc/davinci/davinci-i2s.c3
-rw-r--r--sound/soc/davinci/davinci-mcasp.c3
-rw-r--r--sound/soc/davinci/davinci-pcm.c4
-rw-r--r--sound/soc/davinci/davinci-vcif.c273
-rw-r--r--sound/soc/davinci/davinci-vcif.h28
-rw-r--r--sound/soc/imx/Kconfig8
-rw-r--r--sound/soc/imx/Makefile3
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c8
-rw-r--r--sound/soc/imx/imx-ssi.c7
-rw-r--r--sound/soc/imx/wm1133-ev1.c308
-rw-r--r--sound/soc/omap/mcpdm.c548
-rw-r--r--sound/soc/omap/omap-mcbsp.c42
-rw-r--r--sound/soc/omap/omap-mcpdm.c3
-rw-r--r--sound/soc/omap/omap-pcm.c4
-rw-r--r--sound/soc/pxa/pxa-ssp.c23
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c17
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c7
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c4
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.c21
-rw-r--r--sound/soc/s3c24xx/s3c-dma.c4
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c133
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h4
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.c7
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c40
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h4
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c19
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c12
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h15
-rw-r--r--sound/soc/s6000/s6000-i2s.c3
-rw-r--r--sound/soc/s6000/s6000-pcm.c40
-rw-r--r--sound/soc/soc-cache.c122
-rw-r--r--sound/soc/soc-core.c115
-rw-r--r--sound/soc/soc-dapm.c135
-rw-r--r--sound/soc/soc-jack.c38
67 files changed, 4685 insertions, 1738 deletions
diff --git a/sound/core/jack.c b/sound/core/jack.c
index f705eec7372a..3813e7b04d05 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -23,7 +23,7 @@
23#include <sound/jack.h> 23#include <sound/jack.h>
24#include <sound/core.h> 24#include <sound/core.h>
25 25
26static int jack_types[] = { 26static int jack_switch_types[] = {
27 SW_HEADPHONE_INSERT, 27 SW_HEADPHONE_INSERT,
28 SW_MICROPHONE_INSERT, 28 SW_MICROPHONE_INSERT,
29 SW_LINEOUT_INSERT, 29 SW_LINEOUT_INSERT,
@@ -55,7 +55,7 @@ static int snd_jack_dev_register(struct snd_device *device)
55{ 55{
56 struct snd_jack *jack = device->device_data; 56 struct snd_jack *jack = device->device_data;
57 struct snd_card *card = device->card; 57 struct snd_card *card = device->card;
58 int err; 58 int err, i;
59 59
60 snprintf(jack->name, sizeof(jack->name), "%s %s", 60 snprintf(jack->name, sizeof(jack->name), "%s %s",
61 card->shortname, jack->id); 61 card->shortname, jack->id);
@@ -65,6 +65,19 @@ static int snd_jack_dev_register(struct snd_device *device)
65 if (!jack->input_dev->dev.parent) 65 if (!jack->input_dev->dev.parent)
66 jack->input_dev->dev.parent = snd_card_get_device_link(card); 66 jack->input_dev->dev.parent = snd_card_get_device_link(card);
67 67
68 /* Add capabilities for any keys that are enabled */
69 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
70 int testbit = SND_JACK_BTN_0 >> i;
71
72 if (!(jack->type & testbit))
73 continue;
74
75 if (!jack->key[i])
76 jack->key[i] = BTN_0 + i;
77
78 input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
79 }
80
68 err = input_register_device(jack->input_dev); 81 err = input_register_device(jack->input_dev);
69 if (err == 0) 82 if (err == 0)
70 jack->registered = 1; 83 jack->registered = 1;
@@ -112,10 +125,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
112 125
113 jack->type = type; 126 jack->type = type;
114 127
115 for (i = 0; i < ARRAY_SIZE(jack_types); i++) 128 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++)
116 if (type & (1 << i)) 129 if (type & (1 << i))
117 input_set_capability(jack->input_dev, EV_SW, 130 input_set_capability(jack->input_dev, EV_SW,
118 jack_types[i]); 131 jack_switch_types[i]);
119 132
120 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); 133 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
121 if (err < 0) 134 if (err < 0)
@@ -151,6 +164,43 @@ void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
151EXPORT_SYMBOL(snd_jack_set_parent); 164EXPORT_SYMBOL(snd_jack_set_parent);
152 165
153/** 166/**
167 * snd_jack_set_key - Set a key mapping on a jack
168 *
169 * @jack: The jack to configure
170 * @type: Jack report type for this key
171 * @keytype: Input layer key type to be reported
172 *
173 * Map a SND_JACK_BTN_ button type to an input layer key, allowing
174 * reporting of keys on accessories via the jack abstraction. If no
175 * mapping is provided but keys are enabled in the jack type then
176 * BTN_n numeric buttons will be reported.
177 *
178 * Note that this is intended to be use by simple devices with small
179 * numbers of keys that can be reported. It is also possible to
180 * access the input device directly - devices with complex input
181 * capabilities on accessories should consider doing this rather than
182 * using this abstraction.
183 *
184 * This function may only be called prior to registration of the jack.
185 */
186int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
187 int keytype)
188{
189 int key = fls(SND_JACK_BTN_0) - fls(type);
190
191 WARN_ON(jack->registered);
192
193 if (!keytype || key >= ARRAY_SIZE(jack->key))
194 return -EINVAL;
195
196 jack->type |= type;
197 jack->key[key] = keytype;
198
199 return 0;
200}
201EXPORT_SYMBOL(snd_jack_set_key);
202
203/**
154 * snd_jack_report - Report the current status of a jack 204 * snd_jack_report - Report the current status of a jack
155 * 205 *
156 * @jack: The jack to report status for 206 * @jack: The jack to report status for
@@ -163,10 +213,19 @@ void snd_jack_report(struct snd_jack *jack, int status)
163 if (!jack) 213 if (!jack)
164 return; 214 return;
165 215
166 for (i = 0; i < ARRAY_SIZE(jack_types); i++) { 216 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
217 int testbit = SND_JACK_BTN_0 >> i;
218
219 if (jack->type & testbit)
220 input_report_key(jack->input_dev, jack->key[i],
221 status & testbit);
222 }
223
224 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
167 int testbit = 1 << i; 225 int testbit = 1 << i;
168 if (jack->type & testbit) 226 if (jack->type & testbit)
169 input_report_switch(jack->input_dev, jack_types[i], 227 input_report_switch(jack->input_dev,
228 jack_switch_types[i],
170 status & testbit); 229 status & testbit);
171 } 230 }
172 231
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 9ef6b96373f5..f6b3cc04b34b 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -180,7 +180,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
180 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 180 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
181 runtime->dma_bytes = params_buffer_bytes(params); 181 runtime->dma_bytes = params_buffer_bytes(params);
182 182
183 prtd->params = rtd->dai->cpu_dai->dma_data; 183 prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
184 prtd->params->dma_intr_handler = atmel_pcm_dma_irq; 184 prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
185 185
186 prtd->dma_buffer = runtime->dma_addr; 186 prtd->dma_buffer = runtime->dma_addr;
@@ -415,9 +415,12 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
415} 415}
416 416
417#ifdef CONFIG_PM 417#ifdef CONFIG_PM
418static int atmel_pcm_suspend(struct snd_soc_dai *dai) 418static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
419{ 419{
420 struct snd_pcm_runtime *runtime = dai->runtime; 420 struct snd_pcm *pcm = dai_link->pcm;
421 struct snd_pcm_str *stream = &pcm->streams[0];
422 struct snd_pcm_substream *substream = stream->substream;
423 struct snd_pcm_runtime *runtime = substream->runtime;
421 struct atmel_runtime_data *prtd; 424 struct atmel_runtime_data *prtd;
422 struct atmel_pcm_dma_params *params; 425 struct atmel_pcm_dma_params *params;
423 426
@@ -439,9 +442,12 @@ static int atmel_pcm_suspend(struct snd_soc_dai *dai)
439 return 0; 442 return 0;
440} 443}
441 444
442static int atmel_pcm_resume(struct snd_soc_dai *dai) 445static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
443{ 446{
444 struct snd_pcm_runtime *runtime = dai->runtime; 447 struct snd_pcm *pcm = dai_link->pcm;
448 struct snd_pcm_str *stream = &pcm->streams[0];
449 struct snd_pcm_substream *substream = stream->substream;
450 struct snd_pcm_runtime *runtime = substream->runtime;
445 struct atmel_runtime_data *prtd; 451 struct atmel_runtime_data *prtd;
446 struct atmel_pcm_dma_params *params; 452 struct atmel_pcm_dma_params *params;
447 453
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index e588e63f18d2..0b59806905d1 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -363,12 +363,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
363 ssc_p->dma_params[dir] = dma_params; 363 ssc_p->dma_params[dir] = dma_params;
364 364
365 /* 365 /*
366 * The cpu_dai->dma_data field is only used to communicate the 366 * The snd_soc_pcm_stream->dma_data field is only used to communicate
367 * appropriate DMA parameters to the pcm driver hw_params() 367 * the appropriate DMA parameters to the pcm driver hw_params()
368 * function. It should not be used for other purposes 368 * function. It should not be used for other purposes
369 * as it is common to all substreams. 369 * as it is common to all substreams.
370 */ 370 */
371 rtd->dai->cpu_dai->dma_data = dma_params; 371 snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params);
372 372
373 channels = params_channels(params); 373 channels = params_channels(params);
374 374
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 97f1a251e446..8ef25025f3dc 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -49,13 +49,14 @@ config SND_BF5XX_SOC_AD1836
49 help 49 help
50 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. 50 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
51 51
52config SND_BF5XX_SOC_AD1938 52config SND_BF5XX_SOC_AD193X
53 tristate "SoC AD1938 Audio support for Blackfin" 53 tristate "SoC AD193X Audio support for Blackfin"
54 depends on SND_BF5XX_TDM 54 depends on SND_BF5XX_TDM
55 select SND_BF5XX_SOC_TDM 55 select SND_BF5XX_SOC_TDM
56 select SND_SOC_AD1938 56 select SND_SOC_AD193X
57 help 57 help
58 Say Y if you want to add support for AD1938 codec on Blackfin. 58 Say Y if you want to add support for AD193X codec on Blackfin.
59 This driver supports AD1936, AD1937, AD1938 and AD1939.
59 60
60config SND_BF5XX_AC97 61config SND_BF5XX_AC97
61 tristate "SoC AC97 Audio for the ADI BF5xx chip" 62 tristate "SoC AC97 Audio for the ADI BF5xx chip"
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 87e30423912f..49af3f32aec8 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -20,10 +20,10 @@ snd-ad1836-objs := bf5xx-ad1836.o
20snd-ad1980-objs := bf5xx-ad1980.o 20snd-ad1980-objs := bf5xx-ad1980.o
21snd-ssm2602-objs := bf5xx-ssm2602.o 21snd-ssm2602-objs := bf5xx-ssm2602.o
22snd-ad73311-objs := bf5xx-ad73311.o 22snd-ad73311-objs := bf5xx-ad73311.o
23snd-ad1938-objs := bf5xx-ad1938.o 23snd-ad193x-objs := bf5xx-ad193x.o
24 24
25obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o 25obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
26obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 26obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
27obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 27obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
28obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o 28obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
29obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o 29obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 2ef1e5013b8c..b8c9060cfd8e 100644
--- a/sound/soc/blackfin/bf5xx-ad1938.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * File: sound/soc/blackfin/bf5xx-ad1938.c 2 * File: sound/soc/blackfin/bf5xx-ad193x.c
3 * Author: Barry Song <Barry.Song@analog.com> 3 * Author: Barry Song <Barry.Song@analog.com>
4 * 4 *
5 * Created: Thur June 4 2009 5 * Created: Thur June 4 2009
6 * Description: Board driver for ad1938 sound chip 6 * Description: Board driver for ad193x sound chip
7 * 7 *
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 8 * Bugs: Enter bugs at http://blackfin.uclinux.org/
9 * 9 *
@@ -38,15 +38,15 @@
38#include <asm/dma.h> 38#include <asm/dma.h>
39#include <asm/portmux.h> 39#include <asm/portmux.h>
40 40
41#include "../codecs/ad1938.h" 41#include "../codecs/ad193x.h"
42#include "bf5xx-sport.h" 42#include "bf5xx-sport.h"
43 43
44#include "bf5xx-tdm-pcm.h" 44#include "bf5xx-tdm-pcm.h"
45#include "bf5xx-tdm.h" 45#include "bf5xx-tdm.h"
46 46
47static struct snd_soc_card bf5xx_ad1938; 47static struct snd_soc_card bf5xx_ad193x;
48 48
49static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) 49static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
50{ 50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -55,7 +55,7 @@ static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
55 return 0; 55 return 0;
56} 56}
57 57
58static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, 58static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
59 struct snd_pcm_hw_params *params) 59 struct snd_pcm_hw_params *params)
60{ 60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -89,61 +89,61 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
89 return 0; 89 return 0;
90} 90}
91 91
92static struct snd_soc_ops bf5xx_ad1938_ops = { 92static struct snd_soc_ops bf5xx_ad193x_ops = {
93 .startup = bf5xx_ad1938_startup, 93 .startup = bf5xx_ad193x_startup,
94 .hw_params = bf5xx_ad1938_hw_params, 94 .hw_params = bf5xx_ad193x_hw_params,
95}; 95};
96 96
97static struct snd_soc_dai_link bf5xx_ad1938_dai = { 97static struct snd_soc_dai_link bf5xx_ad193x_dai = {
98 .name = "ad1938", 98 .name = "ad193x",
99 .stream_name = "AD1938", 99 .stream_name = "AD193X",
100 .cpu_dai = &bf5xx_tdm_dai, 100 .cpu_dai = &bf5xx_tdm_dai,
101 .codec_dai = &ad1938_dai, 101 .codec_dai = &ad193x_dai,
102 .ops = &bf5xx_ad1938_ops, 102 .ops = &bf5xx_ad193x_ops,
103}; 103};
104 104
105static struct snd_soc_card bf5xx_ad1938 = { 105static struct snd_soc_card bf5xx_ad193x = {
106 .name = "bf5xx_ad1938", 106 .name = "bf5xx_ad193x",
107 .platform = &bf5xx_tdm_soc_platform, 107 .platform = &bf5xx_tdm_soc_platform,
108 .dai_link = &bf5xx_ad1938_dai, 108 .dai_link = &bf5xx_ad193x_dai,
109 .num_links = 1, 109 .num_links = 1,
110}; 110};
111 111
112static struct snd_soc_device bf5xx_ad1938_snd_devdata = { 112static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
113 .card = &bf5xx_ad1938, 113 .card = &bf5xx_ad193x,
114 .codec_dev = &soc_codec_dev_ad1938, 114 .codec_dev = &soc_codec_dev_ad193x,
115}; 115};
116 116
117static struct platform_device *bfxx_ad1938_snd_device; 117static struct platform_device *bfxx_ad193x_snd_device;
118 118
119static int __init bf5xx_ad1938_init(void) 119static int __init bf5xx_ad193x_init(void)
120{ 120{
121 int ret; 121 int ret;
122 122
123 bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1); 123 bfxx_ad193x_snd_device = platform_device_alloc("soc-audio", -1);
124 if (!bfxx_ad1938_snd_device) 124 if (!bfxx_ad193x_snd_device)
125 return -ENOMEM; 125 return -ENOMEM;
126 126
127 platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata); 127 platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata);
128 bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev; 128 bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
129 ret = platform_device_add(bfxx_ad1938_snd_device); 129 ret = platform_device_add(bfxx_ad193x_snd_device);
130 130
131 if (ret) 131 if (ret)
132 platform_device_put(bfxx_ad1938_snd_device); 132 platform_device_put(bfxx_ad193x_snd_device);
133 133
134 return ret; 134 return ret;
135} 135}
136 136
137static void __exit bf5xx_ad1938_exit(void) 137static void __exit bf5xx_ad193x_exit(void)
138{ 138{
139 platform_device_unregister(bfxx_ad1938_snd_device); 139 platform_device_unregister(bfxx_ad193x_snd_device);
140} 140}
141 141
142module_init(bf5xx_ad1938_init); 142module_init(bf5xx_ad193x_init);
143module_exit(bf5xx_ad1938_exit); 143module_exit(bf5xx_ad193x_exit);
144 144
145/* Module information */ 145/* Module information */
146MODULE_AUTHOR("Barry Song"); 146MODULE_AUTHOR("Barry Song");
147MODULE_DESCRIPTION("ALSA SoC AD1938 board driver"); 147MODULE_DESCRIPTION("ALSA SoC AD193X board driver");
148MODULE_LICENSE("GPL"); 148MODULE_LICENSE("GPL");
149 149
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 2e63dea73e9c..a86e8cc0b2d3 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -34,33 +34,7 @@
34#include <linux/wait.h> 34#include <linux/wait.h>
35#include <linux/workqueue.h> 35#include <linux/workqueue.h>
36#include <asm/dma.h> 36#include <asm/dma.h>
37 37#include <asm/bfin_sport.h>
38struct sport_register {
39 u16 tcr1; u16 reserved0;
40 u16 tcr2; u16 reserved1;
41 u16 tclkdiv; u16 reserved2;
42 u16 tfsdiv; u16 reserved3;
43 u32 tx;
44 u32 reserved_l0;
45 u32 rx;
46 u32 reserved_l1;
47 u16 rcr1; u16 reserved4;
48 u16 rcr2; u16 reserved5;
49 u16 rclkdiv; u16 reserved6;
50 u16 rfsdiv; u16 reserved7;
51 u16 stat; u16 reserved8;
52 u16 chnl; u16 reserved9;
53 u16 mcmc1; u16 reserved10;
54 u16 mcmc2; u16 reserved11;
55 u32 mtcs0;
56 u32 mtcs1;
57 u32 mtcs2;
58 u32 mtcs3;
59 u32 mrcs0;
60 u32 mrcs1;
61 u32 mrcs2;
62 u32 mrcs3;
63};
64 38
65#define DESC_ELEMENT_COUNT 9 39#define DESC_ELEMENT_COUNT 9
66 40
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 1743d565e996..bc0ab47e156b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -13,7 +13,7 @@ config SND_SOC_ALL_CODECS
13 select SND_SOC_L3 13 select SND_SOC_L3
14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
15 select SND_SOC_AD1836 if SPI_MASTER 15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER 16 select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
18 select SND_SOC_ADS117X 18 select SND_SOC_ADS117X
19 select SND_SOC_AD73311 if I2C 19 select SND_SOC_AD73311 if I2C
@@ -21,6 +21,7 @@ config SND_SOC_ALL_CODECS
21 select SND_SOC_AK4535 if I2C 21 select SND_SOC_AK4535 if I2C
22 select SND_SOC_AK4642 if I2C 22 select SND_SOC_AK4642 if I2C
23 select SND_SOC_AK4671 if I2C 23 select SND_SOC_AK4671 if I2C
24 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
24 select SND_SOC_CS4270 if I2C 25 select SND_SOC_CS4270 if I2C
25 select SND_SOC_MAX9877 if I2C 26 select SND_SOC_MAX9877 if I2C
26 select SND_SOC_DA7210 if I2C 27 select SND_SOC_DA7210 if I2C
@@ -34,6 +35,7 @@ config SND_SOC_ALL_CODECS
34 select SND_SOC_TPA6130A2 if I2C 35 select SND_SOC_TPA6130A2 if I2C
35 select SND_SOC_TLV320DAC33 if I2C 36 select SND_SOC_TLV320DAC33 if I2C
36 select SND_SOC_TWL4030 if TWL4030_CORE 37 select SND_SOC_TWL4030 if TWL4030_CORE
38 select SND_SOC_TWL6040 if TWL4030_CORE
37 select SND_SOC_UDA134X 39 select SND_SOC_UDA134X
38 select SND_SOC_UDA1380 if I2C 40 select SND_SOC_UDA1380 if I2C
39 select SND_SOC_WM2000 if I2C 41 select SND_SOC_WM2000 if I2C
@@ -90,7 +92,7 @@ config SND_SOC_AC97_CODEC
90config SND_SOC_AD1836 92config SND_SOC_AD1836
91 tristate 93 tristate
92 94
93config SND_SOC_AD1938 95config SND_SOC_AD193X
94 tristate 96 tristate
95 97
96config SND_SOC_AD1980 98config SND_SOC_AD1980
@@ -114,6 +116,9 @@ config SND_SOC_AK4642
114config SND_SOC_AK4671 116config SND_SOC_AK4671
115 tristate 117 tristate
116 118
119config SND_SOC_CQ0093VC
120 tristate
121
117# Cirrus Logic CS4270 Codec 122# Cirrus Logic CS4270 Codec
118config SND_SOC_CS4270 123config SND_SOC_CS4270
119 tristate 124 tristate
@@ -164,6 +169,9 @@ config SND_SOC_TWL4030
164 select TWL4030_CODEC 169 select TWL4030_CODEC
165 tristate 170 tristate
166 171
172config SND_SOC_TWL6040
173 tristate
174
167config SND_SOC_UDA134X 175config SND_SOC_UDA134X
168 tristate 176 tristate
169 177
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index dd5ce6df6292..337904167358 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,6 +1,6 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1836-objs := ad1836.o 2snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o 3snd-soc-ad193x-objs := ad193x.o
4snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
5snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
6snd-soc-ads117x-objs := ads117x.o 6snd-soc-ads117x-objs := ads117x.o
@@ -8,6 +8,7 @@ snd-soc-ak4104-objs := ak4104.o
8snd-soc-ak4535-objs := ak4535.o 8snd-soc-ak4535-objs := ak4535.o
9snd-soc-ak4642-objs := ak4642.o 9snd-soc-ak4642-objs := ak4642.o
10snd-soc-ak4671-objs := ak4671.o 10snd-soc-ak4671-objs := ak4671.o
11snd-soc-cq93vc-objs := cq93vc.o
11snd-soc-cs4270-objs := cs4270.o 12snd-soc-cs4270-objs := cs4270.o
12snd-soc-cx20442-objs := cx20442.o 13snd-soc-cx20442-objs := cx20442.o
13snd-soc-da7210-objs := da7210.o 14snd-soc-da7210-objs := da7210.o
@@ -21,6 +22,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o
21snd-soc-tlv320aic3x-objs := tlv320aic3x.o 22snd-soc-tlv320aic3x-objs := tlv320aic3x.o
22snd-soc-tlv320dac33-objs := tlv320dac33.o 23snd-soc-tlv320dac33-objs := tlv320dac33.o
23snd-soc-twl4030-objs := twl4030.o 24snd-soc-twl4030-objs := twl4030.o
25snd-soc-twl6040-objs := twl6040.o
24snd-soc-uda134x-objs := uda134x.o 26snd-soc-uda134x-objs := uda134x.o
25snd-soc-uda1380-objs := uda1380.o 27snd-soc-uda1380-objs := uda1380.o
26snd-soc-wm8350-objs := wm8350.o 28snd-soc-wm8350-objs := wm8350.o
@@ -62,7 +64,7 @@ snd-soc-wm2000-objs := wm2000.o
62 64
63obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 65obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
64obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 66obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
65obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o 67obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
66obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 68obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
67obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 69obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
68obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o 70obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
@@ -70,6 +72,7 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
70obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 72obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
71obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 73obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
72obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 74obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
75obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
73obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 76obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
74obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 77obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
75obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 78obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
@@ -83,6 +86,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
83obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 86obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
84obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o 87obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
85obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o 88obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
89obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
86obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 90obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
87obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 91obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
88obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 92obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
deleted file mode 100644
index c233810d463d..000000000000
--- a/sound/soc/codecs/ad1938.c
+++ /dev/null
@@ -1,521 +0,0 @@
1/*
2 * File: sound/soc/codecs/ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: June 04 2009
6 * Description: Driver for AD1938 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/device.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/initval.h>
37#include <sound/soc.h>
38#include <sound/tlv.h>
39#include <sound/soc-dapm.h>
40#include <linux/spi/spi.h>
41#include "ad1938.h"
42
43/* codec private data */
44struct ad1938_priv {
45 struct snd_soc_codec codec;
46 u8 reg_cache[AD1938_NUM_REGS];
47};
48
49/* ad1938 register cache & default register settings */
50static const u8 ad1938_reg[AD1938_NUM_REGS] = {
51 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
52};
53
54static struct snd_soc_codec *ad1938_codec;
55struct snd_soc_codec_device soc_codec_dev_ad1938;
56static int ad1938_register(struct ad1938_priv *ad1938);
57static void ad1938_unregister(struct ad1938_priv *ad1938);
58
59/*
60 * AD1938 volume/mute/de-emphasis etc. controls
61 */
62static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
63
64static const struct soc_enum ad1938_deemp_enum =
65 SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp);
66
67static const struct snd_kcontrol_new ad1938_snd_controls[] = {
68 /* DAC volume control */
69 SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL,
70 AD1938_DAC_R1_VOL, 0, 0xFF, 1),
71 SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL,
72 AD1938_DAC_R2_VOL, 0, 0xFF, 1),
73 SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL,
74 AD1938_DAC_R3_VOL, 0, 0xFF, 1),
75 SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL,
76 AD1938_DAC_R4_VOL, 0, 0xFF, 1),
77
78 /* ADC switch control */
79 SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE,
80 AD1938_ADCR1_MUTE, 1, 1),
81 SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE,
82 AD1938_ADCR2_MUTE, 1, 1),
83
84 /* DAC switch control */
85 SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE,
86 AD1938_DACR1_MUTE, 1, 1),
87 SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE,
88 AD1938_DACR2_MUTE, 1, 1),
89 SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE,
90 AD1938_DACR3_MUTE, 1, 1),
91 SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE,
92 AD1938_DACR4_MUTE, 1, 1),
93
94 /* ADC high-pass filter */
95 SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0,
96 AD1938_ADC_HIGHPASS_FILTER, 1, 0),
97
98 /* DAC de-emphasis */
99 SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum),
100};
101
102static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = {
103 SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1),
104 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
105 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD1938_PLL_CLK_CTRL0, 0, 1, NULL, 0),
106 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0),
107 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
108 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
109 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
110 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
111 SND_SOC_DAPM_INPUT("ADC1IN"),
112 SND_SOC_DAPM_INPUT("ADC2IN"),
113};
114
115static const struct snd_soc_dapm_route audio_paths[] = {
116 { "DAC", NULL, "PLL_PWR" },
117 { "ADC", NULL, "PLL_PWR" },
118 { "DAC", NULL, "ADC_PWR" },
119 { "ADC", NULL, "ADC_PWR" },
120 { "DAC1OUT", "DAC1 Switch", "DAC" },
121 { "DAC2OUT", "DAC2 Switch", "DAC" },
122 { "DAC3OUT", "DAC3 Switch", "DAC" },
123 { "DAC4OUT", "DAC4 Switch", "DAC" },
124 { "ADC", "ADC1 Switch", "ADC1IN" },
125 { "ADC", "ADC2 Switch", "ADC2IN" },
126};
127
128/*
129 * DAI ops entries
130 */
131
132static int ad1938_mute(struct snd_soc_dai *dai, int mute)
133{
134 struct snd_soc_codec *codec = dai->codec;
135 int reg;
136
137 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
138 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
139 (~AD1938_DAC_MASTER_MUTE);
140 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
141
142 return 0;
143}
144
145static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
146 unsigned int rx_mask, int slots, int width)
147{
148 struct snd_soc_codec *codec = dai->codec;
149 int dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
150 int adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
151
152 dac_reg &= ~AD1938_DAC_CHAN_MASK;
153 adc_reg &= ~AD1938_ADC_CHAN_MASK;
154
155 switch (slots) {
156 case 2:
157 dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
158 adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
159 break;
160 case 4:
161 dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
162 adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
163 break;
164 case 8:
165 dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
166 adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
167 break;
168 case 16:
169 dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
170 adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
171 break;
172 default:
173 return -EINVAL;
174 }
175
176 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
177 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
178
179 return 0;
180}
181
182static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
183 unsigned int fmt)
184{
185 struct snd_soc_codec *codec = codec_dai->codec;
186 int adc_reg, dac_reg;
187
188 adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
189 dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
190
191 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
192 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
193 */
194 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
195 case SND_SOC_DAIFMT_I2S:
196 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
197 adc_reg |= AD1938_ADC_SERFMT_TDM;
198 break;
199 case SND_SOC_DAIFMT_DSP_A:
200 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
201 adc_reg |= AD1938_ADC_SERFMT_AUX;
202 break;
203 default:
204 return -EINVAL;
205 }
206
207 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
208 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
209 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
210 adc_reg &= ~AD1938_ADC_BCLK_INV;
211 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
212 dac_reg &= ~AD1938_DAC_BCLK_INV;
213 break;
214 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
215 adc_reg |= AD1938_ADC_LEFT_HIGH;
216 adc_reg &= ~AD1938_ADC_BCLK_INV;
217 dac_reg |= AD1938_DAC_LEFT_HIGH;
218 dac_reg &= ~AD1938_DAC_BCLK_INV;
219 break;
220 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
221 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
222 adc_reg |= AD1938_ADC_BCLK_INV;
223 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
224 dac_reg |= AD1938_DAC_BCLK_INV;
225 break;
226
227 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
228 adc_reg |= AD1938_ADC_LEFT_HIGH;
229 adc_reg |= AD1938_ADC_BCLK_INV;
230 dac_reg |= AD1938_DAC_LEFT_HIGH;
231 dac_reg |= AD1938_DAC_BCLK_INV;
232 break;
233 default:
234 return -EINVAL;
235 }
236
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
239 adc_reg |= AD1938_ADC_LCR_MASTER;
240 adc_reg |= AD1938_ADC_BCLK_MASTER;
241 dac_reg |= AD1938_DAC_LCR_MASTER;
242 dac_reg |= AD1938_DAC_BCLK_MASTER;
243 break;
244 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
245 adc_reg |= AD1938_ADC_LCR_MASTER;
246 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
247 dac_reg |= AD1938_DAC_LCR_MASTER;
248 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
249 break;
250 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
251 adc_reg &= ~AD1938_ADC_LCR_MASTER;
252 adc_reg |= AD1938_ADC_BCLK_MASTER;
253 dac_reg &= ~AD1938_DAC_LCR_MASTER;
254 dac_reg |= AD1938_DAC_BCLK_MASTER;
255 break;
256 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
257 adc_reg &= ~AD1938_ADC_LCR_MASTER;
258 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
259 dac_reg &= ~AD1938_DAC_LCR_MASTER;
260 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
261 break;
262 default:
263 return -EINVAL;
264 }
265
266 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
267 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
268
269 return 0;
270}
271
272static int ad1938_hw_params(struct snd_pcm_substream *substream,
273 struct snd_pcm_hw_params *params,
274 struct snd_soc_dai *dai)
275{
276 int word_len = 0, reg = 0;
277
278 struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 struct snd_soc_device *socdev = rtd->socdev;
280 struct snd_soc_codec *codec = socdev->card->codec;
281
282 /* bit size */
283 switch (params_format(params)) {
284 case SNDRV_PCM_FORMAT_S16_LE:
285 word_len = 3;
286 break;
287 case SNDRV_PCM_FORMAT_S20_3LE:
288 word_len = 1;
289 break;
290 case SNDRV_PCM_FORMAT_S24_LE:
291 case SNDRV_PCM_FORMAT_S32_LE:
292 word_len = 0;
293 break;
294 }
295
296 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
297 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
298 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
299
300 reg = snd_soc_read(codec, AD1938_ADC_CTRL1);
301 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
302 snd_soc_write(codec, AD1938_ADC_CTRL1, reg);
303
304 return 0;
305}
306
307static int __devinit ad1938_spi_probe(struct spi_device *spi)
308{
309 struct snd_soc_codec *codec;
310 struct ad1938_priv *ad1938;
311
312 ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
313 if (ad1938 == NULL)
314 return -ENOMEM;
315
316 codec = &ad1938->codec;
317 codec->control_data = spi;
318 codec->dev = &spi->dev;
319
320 dev_set_drvdata(&spi->dev, ad1938);
321
322 return ad1938_register(ad1938);
323}
324
325static int __devexit ad1938_spi_remove(struct spi_device *spi)
326{
327 struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
328
329 ad1938_unregister(ad1938);
330 return 0;
331}
332
333static struct spi_driver ad1938_spi_driver = {
334 .driver = {
335 .name = "ad1938",
336 .owner = THIS_MODULE,
337 },
338 .probe = ad1938_spi_probe,
339 .remove = __devexit_p(ad1938_spi_remove),
340};
341
342static struct snd_soc_dai_ops ad1938_dai_ops = {
343 .hw_params = ad1938_hw_params,
344 .digital_mute = ad1938_mute,
345 .set_tdm_slot = ad1938_set_tdm_slot,
346 .set_fmt = ad1938_set_dai_fmt,
347};
348
349/* codec DAI instance */
350struct snd_soc_dai ad1938_dai = {
351 .name = "AD1938",
352 .playback = {
353 .stream_name = "Playback",
354 .channels_min = 2,
355 .channels_max = 8,
356 .rates = SNDRV_PCM_RATE_48000,
357 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
358 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
359 },
360 .capture = {
361 .stream_name = "Capture",
362 .channels_min = 2,
363 .channels_max = 4,
364 .rates = SNDRV_PCM_RATE_48000,
365 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
366 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
367 },
368 .ops = &ad1938_dai_ops,
369};
370EXPORT_SYMBOL_GPL(ad1938_dai);
371
372static int ad1938_register(struct ad1938_priv *ad1938)
373{
374 int ret;
375 struct snd_soc_codec *codec = &ad1938->codec;
376
377 if (ad1938_codec) {
378 dev_err(codec->dev, "Another ad1938 is registered\n");
379 return -EINVAL;
380 }
381
382 mutex_init(&codec->mutex);
383 INIT_LIST_HEAD(&codec->dapm_widgets);
384 INIT_LIST_HEAD(&codec->dapm_paths);
385 codec->private_data = ad1938;
386 codec->reg_cache = ad1938->reg_cache;
387 codec->reg_cache_size = AD1938_NUM_REGS;
388 codec->name = "AD1938";
389 codec->owner = THIS_MODULE;
390 codec->dai = &ad1938_dai;
391 codec->num_dai = 1;
392 INIT_LIST_HEAD(&codec->dapm_widgets);
393 INIT_LIST_HEAD(&codec->dapm_paths);
394
395 ad1938_dai.dev = codec->dev;
396 ad1938_codec = codec;
397
398 memcpy(codec->reg_cache, ad1938_reg, AD1938_NUM_REGS);
399
400 ret = snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_SPI);
401 if (ret < 0) {
402 dev_err(codec->dev, "failed to set cache I/O: %d\n",
403 ret);
404 kfree(ad1938);
405 return ret;
406 }
407
408 /* default setting for ad1938 */
409
410 /* unmute dac channels */
411 snd_soc_write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
412 /* de-emphasis: 48kHz, powedown dac */
413 snd_soc_write(codec, AD1938_DAC_CTRL2, 0x1A);
414 /* powerdown dac, dac in tdm mode */
415 snd_soc_write(codec, AD1938_DAC_CTRL0, 0x41);
416 /* high-pass filter enable */
417 snd_soc_write(codec, AD1938_ADC_CTRL0, 0x3);
418 /* sata delay=1, adc aux mode */
419 snd_soc_write(codec, AD1938_ADC_CTRL1, 0x43);
420 /* pll input: mclki/xi */
421 snd_soc_write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
422 snd_soc_write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
423
424 ret = snd_soc_register_codec(codec);
425 if (ret != 0) {
426 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
427 kfree(ad1938);
428 return ret;
429 }
430
431 ret = snd_soc_register_dai(&ad1938_dai);
432 if (ret != 0) {
433 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
434 snd_soc_unregister_codec(codec);
435 kfree(ad1938);
436 return ret;
437 }
438
439 return 0;
440}
441
442static void ad1938_unregister(struct ad1938_priv *ad1938)
443{
444 snd_soc_unregister_dai(&ad1938_dai);
445 snd_soc_unregister_codec(&ad1938->codec);
446 kfree(ad1938);
447 ad1938_codec = NULL;
448}
449
450static int ad1938_probe(struct platform_device *pdev)
451{
452 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
453 struct snd_soc_codec *codec;
454 int ret = 0;
455
456 if (ad1938_codec == NULL) {
457 dev_err(&pdev->dev, "Codec device not registered\n");
458 return -ENODEV;
459 }
460
461 socdev->card->codec = ad1938_codec;
462 codec = ad1938_codec;
463
464 /* register pcms */
465 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
466 if (ret < 0) {
467 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
468 goto pcm_err;
469 }
470
471 snd_soc_add_controls(codec, ad1938_snd_controls,
472 ARRAY_SIZE(ad1938_snd_controls));
473 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
474 ARRAY_SIZE(ad1938_dapm_widgets));
475 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
476
477
478pcm_err:
479 return ret;
480}
481
482/* power down chip */
483static int ad1938_remove(struct platform_device *pdev)
484{
485 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
486
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489
490 return 0;
491}
492
493struct snd_soc_codec_device soc_codec_dev_ad1938 = {
494 .probe = ad1938_probe,
495 .remove = ad1938_remove,
496};
497EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
498
499static int __init ad1938_init(void)
500{
501 int ret;
502
503 ret = spi_register_driver(&ad1938_spi_driver);
504 if (ret != 0) {
505 printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
506 ret);
507 }
508
509 return ret;
510}
511module_init(ad1938_init);
512
513static void __exit ad1938_exit(void)
514{
515 spi_unregister_driver(&ad1938_spi_driver);
516}
517module_exit(ad1938_exit);
518
519MODULE_DESCRIPTION("ASoC ad1938 driver");
520MODULE_AUTHOR("Barry Song ");
521MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1938.h b/sound/soc/codecs/ad1938.h
deleted file mode 100644
index fe3c48cd2d5b..000000000000
--- a/sound/soc/codecs/ad1938.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: May 25, 2009
7 * Description: definitions for AD1938 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#ifndef __AD1938_H__
30#define __AD1938_H__
31
32#define AD1938_PLL_CLK_CTRL0 0
33#define AD1938_PLL_POWERDOWN 0x01
34#define AD1938_PLL_CLK_CTRL1 1
35#define AD1938_DAC_CTRL0 2
36#define AD1938_DAC_POWERDOWN 0x01
37#define AD1938_DAC_SERFMT_MASK 0xC0
38#define AD1938_DAC_SERFMT_STEREO (0 << 6)
39#define AD1938_DAC_SERFMT_TDM (1 << 6)
40#define AD1938_DAC_CTRL1 3
41#define AD1938_DAC_2_CHANNELS 0
42#define AD1938_DAC_4_CHANNELS 1
43#define AD1938_DAC_8_CHANNELS 2
44#define AD1938_DAC_16_CHANNELS 3
45#define AD1938_DAC_CHAN_SHFT 1
46#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT)
47#define AD1938_DAC_LCR_MASTER (1 << 4)
48#define AD1938_DAC_BCLK_MASTER (1 << 5)
49#define AD1938_DAC_LEFT_HIGH (1 << 3)
50#define AD1938_DAC_BCLK_INV (1 << 7)
51#define AD1938_DAC_CTRL2 4
52#define AD1938_DAC_WORD_LEN_MASK 0xC
53#define AD1938_DAC_MASTER_MUTE 1
54#define AD1938_DAC_CHNL_MUTE 5
55#define AD1938_DACL1_MUTE 0
56#define AD1938_DACR1_MUTE 1
57#define AD1938_DACL2_MUTE 2
58#define AD1938_DACR2_MUTE 3
59#define AD1938_DACL3_MUTE 4
60#define AD1938_DACR3_MUTE 5
61#define AD1938_DACL4_MUTE 6
62#define AD1938_DACR4_MUTE 7
63#define AD1938_DAC_L1_VOL 6
64#define AD1938_DAC_R1_VOL 7
65#define AD1938_DAC_L2_VOL 8
66#define AD1938_DAC_R2_VOL 9
67#define AD1938_DAC_L3_VOL 10
68#define AD1938_DAC_R3_VOL 11
69#define AD1938_DAC_L4_VOL 12
70#define AD1938_DAC_R4_VOL 13
71#define AD1938_ADC_CTRL0 14
72#define AD1938_ADC_POWERDOWN 0x01
73#define AD1938_ADC_HIGHPASS_FILTER 1
74#define AD1938_ADCL1_MUTE 2
75#define AD1938_ADCR1_MUTE 3
76#define AD1938_ADCL2_MUTE 4
77#define AD1938_ADCR2_MUTE 5
78#define AD1938_ADC_CTRL1 15
79#define AD1938_ADC_SERFMT_MASK 0x60
80#define AD1938_ADC_SERFMT_STEREO (0 << 5)
81#define AD1938_ADC_SERFMT_TDM (1 << 2)
82#define AD1938_ADC_SERFMT_AUX (2 << 5)
83#define AD1938_ADC_WORD_LEN_MASK 0x3
84#define AD1938_ADC_CTRL2 16
85#define AD1938_ADC_2_CHANNELS 0
86#define AD1938_ADC_4_CHANNELS 1
87#define AD1938_ADC_8_CHANNELS 2
88#define AD1938_ADC_16_CHANNELS 3
89#define AD1938_ADC_CHAN_SHFT 4
90#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT)
91#define AD1938_ADC_LCR_MASTER (1 << 3)
92#define AD1938_ADC_BCLK_MASTER (1 << 6)
93#define AD1938_ADC_LEFT_HIGH (1 << 2)
94#define AD1938_ADC_BCLK_INV (1 << 1)
95
96#define AD1938_NUM_REGS 17
97
98extern struct snd_soc_dai ad1938_dai;
99extern struct snd_soc_codec_device soc_codec_dev_ad1938;
100#endif
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
new file mode 100644
index 000000000000..d034464e26ff
--- /dev/null
+++ b/sound/soc/codecs/ad193x.c
@@ -0,0 +1,558 @@
1/*
2 * AD193X Audio Codec driver supporting AD1936/7/8/9
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/i2c.h>
14#include <linux/spi/spi.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/initval.h>
19#include <sound/soc.h>
20#include <sound/tlv.h>
21#include <sound/soc-dapm.h>
22#include "ad193x.h"
23
24/* codec private data */
25struct ad193x_priv {
26 struct snd_soc_codec codec;
27 u8 reg_cache[AD193X_NUM_REGS];
28};
29
30/* ad193x register cache & default register settings */
31static const u8 ad193x_reg[AD193X_NUM_REGS] = {
32 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
33};
34
35static struct snd_soc_codec *ad193x_codec;
36struct snd_soc_codec_device soc_codec_dev_ad193x;
37static int ad193x_register(struct ad193x_priv *ad193x, int bus_type);
38static void ad193x_unregister(struct ad193x_priv *ad193x);
39
40/*
41 * AD193X volume/mute/de-emphasis etc. controls
42 */
43static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
44
45static const struct soc_enum ad193x_deemp_enum =
46 SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
47
48static const struct snd_kcontrol_new ad193x_snd_controls[] = {
49 /* DAC volume control */
50 SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL,
51 AD193X_DAC_R1_VOL, 0, 0xFF, 1),
52 SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL,
53 AD193X_DAC_R2_VOL, 0, 0xFF, 1),
54 SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL,
55 AD193X_DAC_R3_VOL, 0, 0xFF, 1),
56 SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL,
57 AD193X_DAC_R4_VOL, 0, 0xFF, 1),
58
59 /* ADC switch control */
60 SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
61 AD193X_ADCR1_MUTE, 1, 1),
62 SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE,
63 AD193X_ADCR2_MUTE, 1, 1),
64
65 /* DAC switch control */
66 SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE,
67 AD193X_DACR1_MUTE, 1, 1),
68 SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE,
69 AD193X_DACR2_MUTE, 1, 1),
70 SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE,
71 AD193X_DACR3_MUTE, 1, 1),
72 SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE,
73 AD193X_DACR4_MUTE, 1, 1),
74
75 /* ADC high-pass filter */
76 SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0,
77 AD193X_ADC_HIGHPASS_FILTER, 1, 0),
78
79 /* DAC de-emphasis */
80 SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum),
81};
82
83static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
84 SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1),
85 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
86 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
87 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
88 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
89 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
90 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
91 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
92 SND_SOC_DAPM_INPUT("ADC1IN"),
93 SND_SOC_DAPM_INPUT("ADC2IN"),
94};
95
96static const struct snd_soc_dapm_route audio_paths[] = {
97 { "DAC", NULL, "PLL_PWR" },
98 { "ADC", NULL, "PLL_PWR" },
99 { "DAC", NULL, "ADC_PWR" },
100 { "ADC", NULL, "ADC_PWR" },
101 { "DAC1OUT", "DAC1 Switch", "DAC" },
102 { "DAC2OUT", "DAC2 Switch", "DAC" },
103 { "DAC3OUT", "DAC3 Switch", "DAC" },
104 { "DAC4OUT", "DAC4 Switch", "DAC" },
105 { "ADC", "ADC1 Switch", "ADC1IN" },
106 { "ADC", "ADC2 Switch", "ADC2IN" },
107};
108
109/*
110 * DAI ops entries
111 */
112
113static int ad193x_mute(struct snd_soc_dai *dai, int mute)
114{
115 struct snd_soc_codec *codec = dai->codec;
116 int reg;
117
118 reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
119 reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
120 (~AD193X_DAC_MASTER_MUTE);
121 snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
122
123 return 0;
124}
125
126static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
127 unsigned int rx_mask, int slots, int width)
128{
129 struct snd_soc_codec *codec = dai->codec;
130 int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
131 int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
132
133 dac_reg &= ~AD193X_DAC_CHAN_MASK;
134 adc_reg &= ~AD193X_ADC_CHAN_MASK;
135
136 switch (slots) {
137 case 2:
138 dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT;
139 adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT;
140 break;
141 case 4:
142 dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT;
143 adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT;
144 break;
145 case 8:
146 dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT;
147 adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT;
148 break;
149 case 16:
150 dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT;
151 adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT;
152 break;
153 default:
154 return -EINVAL;
155 }
156
157 snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
158 snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
159
160 return 0;
161}
162
163static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
164 unsigned int fmt)
165{
166 struct snd_soc_codec *codec = codec_dai->codec;
167 int adc_reg, dac_reg;
168
169 adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
170 dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
171
172 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
173 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
174 */
175 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
176 case SND_SOC_DAIFMT_I2S:
177 adc_reg &= ~AD193X_ADC_SERFMT_MASK;
178 adc_reg |= AD193X_ADC_SERFMT_TDM;
179 break;
180 case SND_SOC_DAIFMT_DSP_A:
181 adc_reg &= ~AD193X_ADC_SERFMT_MASK;
182 adc_reg |= AD193X_ADC_SERFMT_AUX;
183 break;
184 default:
185 return -EINVAL;
186 }
187
188 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
189 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
190 adc_reg &= ~AD193X_ADC_LEFT_HIGH;
191 adc_reg &= ~AD193X_ADC_BCLK_INV;
192 dac_reg &= ~AD193X_DAC_LEFT_HIGH;
193 dac_reg &= ~AD193X_DAC_BCLK_INV;
194 break;
195 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
196 adc_reg |= AD193X_ADC_LEFT_HIGH;
197 adc_reg &= ~AD193X_ADC_BCLK_INV;
198 dac_reg |= AD193X_DAC_LEFT_HIGH;
199 dac_reg &= ~AD193X_DAC_BCLK_INV;
200 break;
201 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
202 adc_reg &= ~AD193X_ADC_LEFT_HIGH;
203 adc_reg |= AD193X_ADC_BCLK_INV;
204 dac_reg &= ~AD193X_DAC_LEFT_HIGH;
205 dac_reg |= AD193X_DAC_BCLK_INV;
206 break;
207
208 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
209 adc_reg |= AD193X_ADC_LEFT_HIGH;
210 adc_reg |= AD193X_ADC_BCLK_INV;
211 dac_reg |= AD193X_DAC_LEFT_HIGH;
212 dac_reg |= AD193X_DAC_BCLK_INV;
213 break;
214 default:
215 return -EINVAL;
216 }
217
218 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
219 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
220 adc_reg |= AD193X_ADC_LCR_MASTER;
221 adc_reg |= AD193X_ADC_BCLK_MASTER;
222 dac_reg |= AD193X_DAC_LCR_MASTER;
223 dac_reg |= AD193X_DAC_BCLK_MASTER;
224 break;
225 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
226 adc_reg |= AD193X_ADC_LCR_MASTER;
227 adc_reg &= ~AD193X_ADC_BCLK_MASTER;
228 dac_reg |= AD193X_DAC_LCR_MASTER;
229 dac_reg &= ~AD193X_DAC_BCLK_MASTER;
230 break;
231 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
232 adc_reg &= ~AD193X_ADC_LCR_MASTER;
233 adc_reg |= AD193X_ADC_BCLK_MASTER;
234 dac_reg &= ~AD193X_DAC_LCR_MASTER;
235 dac_reg |= AD193X_DAC_BCLK_MASTER;
236 break;
237 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
238 adc_reg &= ~AD193X_ADC_LCR_MASTER;
239 adc_reg &= ~AD193X_ADC_BCLK_MASTER;
240 dac_reg &= ~AD193X_DAC_LCR_MASTER;
241 dac_reg &= ~AD193X_DAC_BCLK_MASTER;
242 break;
243 default:
244 return -EINVAL;
245 }
246
247 snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
248 snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
249
250 return 0;
251}
252
253static int ad193x_hw_params(struct snd_pcm_substream *substream,
254 struct snd_pcm_hw_params *params,
255 struct snd_soc_dai *dai)
256{
257 int word_len = 0, reg = 0;
258
259 struct snd_soc_pcm_runtime *rtd = substream->private_data;
260 struct snd_soc_device *socdev = rtd->socdev;
261 struct snd_soc_codec *codec = socdev->card->codec;
262
263 /* bit size */
264 switch (params_format(params)) {
265 case SNDRV_PCM_FORMAT_S16_LE:
266 word_len = 3;
267 break;
268 case SNDRV_PCM_FORMAT_S20_3LE:
269 word_len = 1;
270 break;
271 case SNDRV_PCM_FORMAT_S24_LE:
272 case SNDRV_PCM_FORMAT_S32_LE:
273 word_len = 0;
274 break;
275 }
276
277 reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
278 reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len;
279 snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
280
281 reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
282 reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
283 snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
284
285 return 0;
286}
287
288static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
289{
290 struct snd_soc_codec *codec;
291 struct ad193x_priv *ad193x;
292
293 ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
294 if (ad193x == NULL)
295 return -ENOMEM;
296
297 codec = &ad193x->codec;
298 codec->control_data = ctrl_data;
299 codec->dev = dev;
300
301 dev_set_drvdata(dev, ad193x);
302
303 return ad193x_register(ad193x, bus_type);
304}
305
306static int ad193x_bus_remove(struct device *dev)
307{
308 struct ad193x_priv *ad193x = dev_get_drvdata(dev);
309
310 ad193x_unregister(ad193x);
311 return 0;
312}
313
314static struct snd_soc_dai_ops ad193x_dai_ops = {
315 .hw_params = ad193x_hw_params,
316 .digital_mute = ad193x_mute,
317 .set_tdm_slot = ad193x_set_tdm_slot,
318 .set_fmt = ad193x_set_dai_fmt,
319};
320
321/* codec DAI instance */
322struct snd_soc_dai ad193x_dai = {
323 .name = "AD193X",
324 .playback = {
325 .stream_name = "Playback",
326 .channels_min = 2,
327 .channels_max = 8,
328 .rates = SNDRV_PCM_RATE_48000,
329 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
330 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
331 },
332 .capture = {
333 .stream_name = "Capture",
334 .channels_min = 2,
335 .channels_max = 4,
336 .rates = SNDRV_PCM_RATE_48000,
337 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
338 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
339 },
340 .ops = &ad193x_dai_ops,
341};
342EXPORT_SYMBOL_GPL(ad193x_dai);
343
344static int ad193x_register(struct ad193x_priv *ad193x, int bus_type)
345{
346 int ret;
347 struct snd_soc_codec *codec = &ad193x->codec;
348
349 if (ad193x_codec) {
350 dev_err(codec->dev, "Another ad193x is registered\n");
351 return -EINVAL;
352 }
353
354 mutex_init(&codec->mutex);
355 codec->private_data = ad193x;
356 codec->reg_cache = ad193x->reg_cache;
357 codec->reg_cache_size = AD193X_NUM_REGS;
358 codec->name = "AD193X";
359 codec->owner = THIS_MODULE;
360 codec->dai = &ad193x_dai;
361 codec->num_dai = 1;
362 INIT_LIST_HEAD(&codec->dapm_widgets);
363 INIT_LIST_HEAD(&codec->dapm_paths);
364
365 ad193x_dai.dev = codec->dev;
366 ad193x_codec = codec;
367
368 memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
369
370 if (bus_type == SND_SOC_I2C)
371 ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
372 else
373 ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
374 if (ret < 0) {
375 dev_err(codec->dev, "failed to set cache I/O: %d\n",
376 ret);
377 kfree(ad193x);
378 return ret;
379 }
380
381 /* default setting for ad193x */
382
383 /* unmute dac channels */
384 snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
385 /* de-emphasis: 48kHz, powedown dac */
386 snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
387 /* powerdown dac, dac in tdm mode */
388 snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
389 /* high-pass filter enable */
390 snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
391 /* sata delay=1, adc aux mode */
392 snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
393 /* pll input: mclki/xi */
394 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
395 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
396
397 ret = snd_soc_register_codec(codec);
398 if (ret != 0) {
399 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
400 kfree(ad193x);
401 return ret;
402 }
403
404 ret = snd_soc_register_dai(&ad193x_dai);
405 if (ret != 0) {
406 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
407 snd_soc_unregister_codec(codec);
408 kfree(ad193x);
409 return ret;
410 }
411
412 return 0;
413}
414
415static void ad193x_unregister(struct ad193x_priv *ad193x)
416{
417 snd_soc_unregister_dai(&ad193x_dai);
418 snd_soc_unregister_codec(&ad193x->codec);
419 kfree(ad193x);
420 ad193x_codec = NULL;
421}
422
423static int ad193x_probe(struct platform_device *pdev)
424{
425 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
426 struct snd_soc_codec *codec;
427 int ret = 0;
428
429 if (ad193x_codec == NULL) {
430 dev_err(&pdev->dev, "Codec device not registered\n");
431 return -ENODEV;
432 }
433
434 socdev->card->codec = ad193x_codec;
435 codec = ad193x_codec;
436
437 /* register pcms */
438 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
439 if (ret < 0) {
440 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
441 goto pcm_err;
442 }
443
444 snd_soc_add_controls(codec, ad193x_snd_controls,
445 ARRAY_SIZE(ad193x_snd_controls));
446 snd_soc_dapm_new_controls(codec, ad193x_dapm_widgets,
447 ARRAY_SIZE(ad193x_dapm_widgets));
448 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
449
450pcm_err:
451 return ret;
452}
453
454/* power down chip */
455static int ad193x_remove(struct platform_device *pdev)
456{
457 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
458
459 snd_soc_free_pcms(socdev);
460 snd_soc_dapm_free(socdev);
461
462 return 0;
463}
464
465struct snd_soc_codec_device soc_codec_dev_ad193x = {
466 .probe = ad193x_probe,
467 .remove = ad193x_remove,
468};
469EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
470
471#if defined(CONFIG_SPI_MASTER)
472static int __devinit ad193x_spi_probe(struct spi_device *spi)
473{
474 return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
475}
476
477static int __devexit ad193x_spi_remove(struct spi_device *spi)
478{
479 return ad193x_bus_remove(&spi->dev);
480}
481
482static struct spi_driver ad193x_spi_driver = {
483 .driver = {
484 .name = "ad193x",
485 .owner = THIS_MODULE,
486 },
487 .probe = ad193x_spi_probe,
488 .remove = __devexit_p(ad193x_spi_remove),
489};
490#endif
491
492#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
493static const struct i2c_device_id ad193x_id[] = {
494 { "ad1936", 0 },
495 { "ad1937", 0 },
496 { }
497};
498MODULE_DEVICE_TABLE(i2c, ad193x_id);
499
500static int __devinit ad193x_i2c_probe(struct i2c_client *client,
501 const struct i2c_device_id *id)
502{
503 return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C);
504}
505
506static int __devexit ad193x_i2c_remove(struct i2c_client *client)
507{
508 return ad193x_bus_remove(&client->dev);
509}
510
511static struct i2c_driver ad193x_i2c_driver = {
512 .driver = {
513 .name = "ad193x",
514 },
515 .probe = ad193x_i2c_probe,
516 .remove = __devexit_p(ad193x_i2c_remove),
517 .id_table = ad193x_id,
518};
519#endif
520
521static int __init ad193x_modinit(void)
522{
523 int ret;
524
525#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
526 ret = i2c_add_driver(&ad193x_i2c_driver);
527 if (ret != 0) {
528 printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
529 ret);
530 }
531#endif
532
533#if defined(CONFIG_SPI_MASTER)
534 ret = spi_register_driver(&ad193x_spi_driver);
535 if (ret != 0) {
536 printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n",
537 ret);
538 }
539#endif
540 return ret;
541}
542module_init(ad193x_modinit);
543
544static void __exit ad193x_modexit(void)
545{
546#if defined(CONFIG_SPI_MASTER)
547 spi_unregister_driver(&ad193x_spi_driver);
548#endif
549
550#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
551 i2c_del_driver(&ad193x_i2c_driver);
552#endif
553}
554module_exit(ad193x_modexit);
555
556MODULE_DESCRIPTION("ASoC ad193x driver");
557MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
558MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
new file mode 100644
index 000000000000..a03c880d52f9
--- /dev/null
+++ b/sound/soc/codecs/ad193x.h
@@ -0,0 +1,81 @@
1/*
2 * AD193X Audio Codec driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#ifndef __AD193X_H__
10#define __AD193X_H__
11
12#define AD193X_PLL_CLK_CTRL0 0x800
13#define AD193X_PLL_POWERDOWN 0x01
14#define AD193X_PLL_CLK_CTRL1 0x801
15#define AD193X_DAC_CTRL0 0x802
16#define AD193X_DAC_POWERDOWN 0x01
17#define AD193X_DAC_SERFMT_MASK 0xC0
18#define AD193X_DAC_SERFMT_STEREO (0 << 6)
19#define AD193X_DAC_SERFMT_TDM (1 << 6)
20#define AD193X_DAC_CTRL1 0x803
21#define AD193X_DAC_2_CHANNELS 0
22#define AD193X_DAC_4_CHANNELS 1
23#define AD193X_DAC_8_CHANNELS 2
24#define AD193X_DAC_16_CHANNELS 3
25#define AD193X_DAC_CHAN_SHFT 1
26#define AD193X_DAC_CHAN_MASK (3 << AD193X_DAC_CHAN_SHFT)
27#define AD193X_DAC_LCR_MASTER (1 << 4)
28#define AD193X_DAC_BCLK_MASTER (1 << 5)
29#define AD193X_DAC_LEFT_HIGH (1 << 3)
30#define AD193X_DAC_BCLK_INV (1 << 7)
31#define AD193X_DAC_CTRL2 0x804
32#define AD193X_DAC_WORD_LEN_MASK 0xC
33#define AD193X_DAC_MASTER_MUTE 1
34#define AD193X_DAC_CHNL_MUTE 0x805
35#define AD193X_DACL1_MUTE 0
36#define AD193X_DACR1_MUTE 1
37#define AD193X_DACL2_MUTE 2
38#define AD193X_DACR2_MUTE 3
39#define AD193X_DACL3_MUTE 4
40#define AD193X_DACR3_MUTE 5
41#define AD193X_DACL4_MUTE 6
42#define AD193X_DACR4_MUTE 7
43#define AD193X_DAC_L1_VOL 0x806
44#define AD193X_DAC_R1_VOL 0x807
45#define AD193X_DAC_L2_VOL 0x808
46#define AD193X_DAC_R2_VOL 0x809
47#define AD193X_DAC_L3_VOL 0x80a
48#define AD193X_DAC_R3_VOL 0x80b
49#define AD193X_DAC_L4_VOL 0x80c
50#define AD193X_DAC_R4_VOL 0x80d
51#define AD193X_ADC_CTRL0 0x80e
52#define AD193X_ADC_POWERDOWN 0x01
53#define AD193X_ADC_HIGHPASS_FILTER 1
54#define AD193X_ADCL1_MUTE 2
55#define AD193X_ADCR1_MUTE 3
56#define AD193X_ADCL2_MUTE 4
57#define AD193X_ADCR2_MUTE 5
58#define AD193X_ADC_CTRL1 0x80f
59#define AD193X_ADC_SERFMT_MASK 0x60
60#define AD193X_ADC_SERFMT_STEREO (0 << 5)
61#define AD193X_ADC_SERFMT_TDM (1 << 2)
62#define AD193X_ADC_SERFMT_AUX (2 << 5)
63#define AD193X_ADC_WORD_LEN_MASK 0x3
64#define AD193X_ADC_CTRL2 0x810
65#define AD193X_ADC_2_CHANNELS 0
66#define AD193X_ADC_4_CHANNELS 1
67#define AD193X_ADC_8_CHANNELS 2
68#define AD193X_ADC_16_CHANNELS 3
69#define AD193X_ADC_CHAN_SHFT 4
70#define AD193X_ADC_CHAN_MASK (3 << AD193X_ADC_CHAN_SHFT)
71#define AD193X_ADC_LCR_MASTER (1 << 3)
72#define AD193X_ADC_BCLK_MASTER (1 << 6)
73#define AD193X_ADC_LEFT_HIGH (1 << 2)
74#define AD193X_ADC_BCLK_INV (1 << 1)
75
76#define AD193X_NUM_REGS 17
77
78extern struct snd_soc_dai ad193x_dai;
79extern struct snd_soc_codec_device soc_codec_dev_ad193x;
80
81#endif
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
new file mode 100644
index 000000000000..513297441369
--- /dev/null
+++ b/sound/soc/codecs/cq93vc.c
@@ -0,0 +1,298 @@
1/*
2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/io.h>
26#include <linux/delay.h>
27#include <linux/pm.h>
28#include <linux/platform_device.h>
29#include <linux/device.h>
30#include <linux/clk.h>
31#include <linux/mfd/davinci_voicecodec.h>
32
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-dai.h>
38#include <sound/soc-dapm.h>
39#include <sound/initval.h>
40
41#include <mach/dm365.h>
42
43#include "cq93vc.h"
44
45static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
46 unsigned int reg)
47{
48 struct davinci_vc *davinci_vc = codec->control_data;
49
50 return readl(davinci_vc->base + reg);
51}
52
53static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
54 unsigned int value)
55{
56 struct davinci_vc *davinci_vc = codec->control_data;
57
58 writel(value, davinci_vc->base + reg);
59
60 return 0;
61}
62
63static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
64 SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
65 SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
66};
67
68static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
69{
70 struct snd_soc_codec *codec = dai->codec;
71 u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
72
73 if (mute)
74 cq93vc_write(codec, DAVINCI_VC_REG09,
75 reg | DAVINCI_VC_REG09_MUTE);
76 else
77 cq93vc_write(codec, DAVINCI_VC_REG09, reg);
78
79 return 0;
80}
81
82static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
83 int clk_id, unsigned int freq, int dir)
84{
85 struct snd_soc_codec *codec = codec_dai->codec;
86 struct davinci_vc *davinci_vc = codec->control_data;
87
88 switch (freq) {
89 case 22579200:
90 case 27000000:
91 case 33868800:
92 davinci_vc->cq93vc.sysclk = freq;
93 return 0;
94 }
95
96 return -EINVAL;
97}
98
99static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
100 enum snd_soc_bias_level level)
101{
102 switch (level) {
103 case SND_SOC_BIAS_ON:
104 cq93vc_write(codec, DAVINCI_VC_REG12,
105 DAVINCI_VC_REG12_POWER_ALL_ON);
106 break;
107 case SND_SOC_BIAS_PREPARE:
108 break;
109 case SND_SOC_BIAS_STANDBY:
110 cq93vc_write(codec, DAVINCI_VC_REG12,
111 DAVINCI_VC_REG12_POWER_ALL_OFF);
112 break;
113 case SND_SOC_BIAS_OFF:
114 /* force all power off */
115 cq93vc_write(codec, DAVINCI_VC_REG12,
116 DAVINCI_VC_REG12_POWER_ALL_OFF);
117 break;
118 }
119 codec->bias_level = level;
120
121 return 0;
122}
123
124#define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
125#define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
126
127static struct snd_soc_dai_ops cq93vc_dai_ops = {
128 .digital_mute = cq93vc_mute,
129 .set_sysclk = cq93vc_set_dai_sysclk,
130};
131
132struct snd_soc_dai cq93vc_dai = {
133 .name = "CQ93VC",
134 .playback = {
135 .stream_name = "Playback",
136 .channels_min = 1,
137 .channels_max = 2,
138 .rates = CQ93VC_RATES,
139 .formats = CQ93VC_FORMATS,},
140 .capture = {
141 .stream_name = "Capture",
142 .channels_min = 1,
143 .channels_max = 2,
144 .rates = CQ93VC_RATES,
145 .formats = CQ93VC_FORMATS,},
146 .ops = &cq93vc_dai_ops,
147};
148EXPORT_SYMBOL_GPL(cq93vc_dai);
149
150static int cq93vc_resume(struct platform_device *pdev)
151{
152 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
153 struct snd_soc_codec *codec = socdev->card->codec;
154
155 cq93vc_set_bias_level(codec, codec->suspend_bias_level);
156
157 return 0;
158}
159
160static struct snd_soc_codec *cq93vc_codec;
161
162static int cq93vc_probe(struct platform_device *pdev)
163{
164 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
165 struct device *dev = &pdev->dev;
166 struct snd_soc_codec *codec;
167 int ret;
168
169 socdev->card->codec = cq93vc_codec;
170 codec = socdev->card->codec;
171
172 /* Register pcms */
173 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
174 if (ret < 0) {
175 dev_err(dev, "%s: failed to create pcms\n", pdev->name);
176 return ret;
177 }
178
179 /* Set controls */
180 snd_soc_add_controls(codec, cq93vc_snd_controls,
181 ARRAY_SIZE(cq93vc_snd_controls));
182
183 /* Off, with power on */
184 cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
185
186 return 0;
187}
188
189static int cq93vc_remove(struct platform_device *pdev)
190{
191 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
192
193 snd_soc_free_pcms(socdev);
194 snd_soc_dapm_free(socdev);
195
196 return 0;
197}
198
199struct snd_soc_codec_device soc_codec_dev_cq93vc = {
200 .probe = cq93vc_probe,
201 .remove = cq93vc_remove,
202 .resume = cq93vc_resume,
203};
204EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
205
206static __init int cq93vc_codec_probe(struct platform_device *pdev)
207{
208 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
209 struct snd_soc_codec *codec;
210 int ret;
211
212 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
213 if (codec == NULL) {
214 dev_dbg(davinci_vc->dev,
215 "could not allocate memory for codec data\n");
216 return -ENOMEM;
217 }
218
219 davinci_vc->cq93vc.codec = codec;
220
221 cq93vc_dai.dev = &pdev->dev;
222
223 mutex_init(&codec->mutex);
224 INIT_LIST_HEAD(&codec->dapm_widgets);
225 INIT_LIST_HEAD(&codec->dapm_paths);
226 codec->dev = &pdev->dev;
227 codec->name = "CQ93VC";
228 codec->owner = THIS_MODULE;
229 codec->read = cq93vc_read;
230 codec->write = cq93vc_write;
231 codec->set_bias_level = cq93vc_set_bias_level;
232 codec->dai = &cq93vc_dai;
233 codec->num_dai = 1;
234 codec->control_data = davinci_vc;
235
236 cq93vc_codec = codec;
237
238 ret = snd_soc_register_codec(codec);
239 if (ret) {
240 dev_err(davinci_vc->dev, "failed to register codec\n");
241 goto fail1;
242 }
243
244 ret = snd_soc_register_dai(&cq93vc_dai);
245 if (ret) {
246 dev_err(davinci_vc->dev, "could register dai\n");
247 goto fail2;
248 }
249 return 0;
250
251fail2:
252 snd_soc_unregister_codec(codec);
253
254fail1:
255 kfree(codec);
256 cq93vc_codec = NULL;
257
258 return ret;
259}
260
261static int __devexit cq93vc_codec_remove(struct platform_device *pdev)
262{
263 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
264 struct snd_soc_codec *codec = socdev->card->codec;
265
266 snd_soc_unregister_dai(&cq93vc_dai);
267 snd_soc_unregister_codec(&codec);
268
269 kfree(codec);
270 cq93vc_codec = NULL;
271
272 return 0;
273}
274
275static struct platform_driver cq93vc_codec_driver = {
276 .driver = {
277 .name = "cq93vc",
278 .owner = THIS_MODULE,
279 },
280 .probe = cq93vc_codec_probe,
281 .remove = __devexit_p(cq93vc_codec_remove),
282};
283
284static __init int cq93vc_init(void)
285{
286 return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe);
287}
288module_init(cq93vc_init);
289
290static __exit void cq93vc_exit(void)
291{
292 platform_driver_unregister(&cq93vc_codec_driver);
293}
294module_exit(cq93vc_exit);
295
296MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
297MODULE_AUTHOR("Miguel Aguilar");
298MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h
new file mode 100644
index 000000000000..845b1968ef9c
--- /dev/null
+++ b/sound/soc/codecs/cq93vc.h
@@ -0,0 +1,29 @@
1/*
2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _CQ93VC_H
24#define _CQ93VC_H
25
26extern struct snd_soc_dai cq93vc_dai;
27extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
28
29#endif
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index cf2975a7294a..35b881638658 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -55,8 +55,14 @@
55#define DA7210_DAI_SRC_SEL 0x25 55#define DA7210_DAI_SRC_SEL 0x25
56#define DA7210_DAI_CFG1 0x26 56#define DA7210_DAI_CFG1 0x26
57#define DA7210_DAI_CFG3 0x28 57#define DA7210_DAI_CFG3 0x28
58#define DA7210_PLL_DIV1 0x29
59#define DA7210_PLL_DIV2 0x2A
58#define DA7210_PLL_DIV3 0x2B 60#define DA7210_PLL_DIV3 0x2B
59#define DA7210_PLL 0x2C 61#define DA7210_PLL 0x2C
62#define DA7210_A_HID_UNLOCK 0x8A
63#define DA7210_A_TEST_UNLOCK 0x8B
64#define DA7210_A_PLL1 0x90
65#define DA7210_A_CP_MODE 0xA7
60 66
61/* STARTUP1 bit fields */ 67/* STARTUP1 bit fields */
62#define DA7210_SC_MST_EN (1 << 0) 68#define DA7210_SC_MST_EN (1 << 0)
@@ -74,15 +80,14 @@
74/* INMIX_R bit fields */ 80/* INMIX_R bit fields */
75#define DA7210_IN_R_EN (1 << 7) 81#define DA7210_IN_R_EN (1 << 7)
76 82
77/* ADC_HPF bit fields */
78#define DA7210_ADC_VOICE_EN (1 << 7)
79
80/* ADC bit fields */ 83/* ADC bit fields */
81#define DA7210_ADC_L_EN (1 << 3) 84#define DA7210_ADC_L_EN (1 << 3)
82#define DA7210_ADC_R_EN (1 << 7) 85#define DA7210_ADC_R_EN (1 << 7)
83 86
84/* DAC_HPF fields */ 87/* DAC/ADC HPF fields */
85#define DA7210_DAC_VOICE_EN (1 << 7) 88#define DA7210_VOICE_F0_MASK (0x7 << 4)
89#define DA7210_VOICE_F0_25 (1 << 4)
90#define DA7210_VOICE_EN (1 << 7)
86 91
87/* DAC_SEL bit fields */ 92/* DAC_SEL bit fields */
88#define DA7210_DAC_L_SRC_DAI_L (4 << 0) 93#define DA7210_DAC_L_SRC_DAI_L (4 << 0)
@@ -123,7 +128,19 @@
123#define DA7210_PLL_BYP (1 << 6) 128#define DA7210_PLL_BYP (1 << 6)
124 129
125/* PLL bit fields */ 130/* PLL bit fields */
126#define DA7210_PLL_FS_48000 (11 << 0) 131#define DA7210_PLL_FS_MASK (0xF << 0)
132#define DA7210_PLL_FS_8000 (0x1 << 0)
133#define DA7210_PLL_FS_11025 (0x2 << 0)
134#define DA7210_PLL_FS_12000 (0x3 << 0)
135#define DA7210_PLL_FS_16000 (0x5 << 0)
136#define DA7210_PLL_FS_22050 (0x6 << 0)
137#define DA7210_PLL_FS_24000 (0x7 << 0)
138#define DA7210_PLL_FS_32000 (0x9 << 0)
139#define DA7210_PLL_FS_44100 (0xA << 0)
140#define DA7210_PLL_FS_48000 (0xB << 0)
141#define DA7210_PLL_FS_88200 (0xE << 0)
142#define DA7210_PLL_FS_96000 (0xF << 0)
143#define DA7210_PLL_EN (0x1 << 7)
127 144
128#define DA7210_VERSION "0.0.1" 145#define DA7210_VERSION "0.0.1"
129 146
@@ -241,7 +258,8 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
241 struct snd_soc_device *socdev = rtd->socdev; 258 struct snd_soc_device *socdev = rtd->socdev;
242 struct snd_soc_codec *codec = socdev->card->codec; 259 struct snd_soc_codec *codec = socdev->card->codec;
243 u32 dai_cfg1; 260 u32 dai_cfg1;
244 u32 reg, mask; 261 u32 hpf_reg, hpf_mask, hpf_value;
262 u32 fs, bypass;
245 263
246 /* set DAI source to Left and Right ADC */ 264 /* set DAI source to Left and Right ADC */
247 da7210_write(codec, DA7210_DAI_SRC_SEL, 265 da7210_write(codec, DA7210_DAI_SRC_SEL,
@@ -265,25 +283,84 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
265 283
266 da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); 284 da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
267 285
268 /* FIXME 286 hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
269 * 287 DA7210_DAC_HPF : DA7210_ADC_HPF;
270 * It support 48K only now 288
271 */
272 switch (params_rate(params)) { 289 switch (params_rate(params)) {
290 case 8000:
291 fs = DA7210_PLL_FS_8000;
292 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
293 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
294 bypass = DA7210_PLL_BYP;
295 break;
296 case 11025:
297 fs = DA7210_PLL_FS_11025;
298 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
299 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
300 bypass = 0;
301 break;
302 case 12000:
303 fs = DA7210_PLL_FS_12000;
304 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
305 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
306 bypass = DA7210_PLL_BYP;
307 break;
308 case 16000:
309 fs = DA7210_PLL_FS_16000;
310 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
311 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
312 bypass = DA7210_PLL_BYP;
313 break;
314 case 22050:
315 fs = DA7210_PLL_FS_22050;
316 hpf_mask = DA7210_VOICE_EN;
317 hpf_value = 0;
318 bypass = 0;
319 break;
320 case 32000:
321 fs = DA7210_PLL_FS_32000;
322 hpf_mask = DA7210_VOICE_EN;
323 hpf_value = 0;
324 bypass = DA7210_PLL_BYP;
325 break;
326 case 44100:
327 fs = DA7210_PLL_FS_44100;
328 hpf_mask = DA7210_VOICE_EN;
329 hpf_value = 0;
330 bypass = 0;
331 break;
273 case 48000: 332 case 48000:
274 if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { 333 fs = DA7210_PLL_FS_48000;
275 reg = DA7210_DAC_HPF; 334 hpf_mask = DA7210_VOICE_EN;
276 mask = DA7210_DAC_VOICE_EN; 335 hpf_value = 0;
277 } else { 336 bypass = DA7210_PLL_BYP;
278 reg = DA7210_ADC_HPF; 337 break;
279 mask = DA7210_ADC_VOICE_EN; 338 case 88200:
280 } 339 fs = DA7210_PLL_FS_88200;
340 hpf_mask = DA7210_VOICE_EN;
341 hpf_value = 0;
342 bypass = 0;
343 break;
344 case 96000:
345 fs = DA7210_PLL_FS_96000;
346 hpf_mask = DA7210_VOICE_EN;
347 hpf_value = 0;
348 bypass = DA7210_PLL_BYP;
281 break; 349 break;
282 default: 350 default:
283 return -EINVAL; 351 return -EINVAL;
284 } 352 }
285 353
286 snd_soc_update_bits(codec, reg, mask, 0); 354 /* Disable active mode */
355 snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
356
357 snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
358 snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
359 snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
360
361 /* Enable active mode */
362 snd_soc_update_bits(codec, DA7210_STARTUP1,
363 DA7210_SC_MST_EN, DA7210_SC_MST_EN);
287 364
288 return 0; 365 return 0;
289} 366}
@@ -361,6 +438,7 @@ struct snd_soc_dai da7210_dai = {
361 .formats = DA7210_FORMATS, 438 .formats = DA7210_FORMATS,
362 }, 439 },
363 .ops = &da7210_dai_ops, 440 .ops = &da7210_dai_ops,
441 .symmetric_rates = 1,
364}; 442};
365EXPORT_SYMBOL_GPL(da7210_dai); 443EXPORT_SYMBOL_GPL(da7210_dai);
366 444
@@ -415,9 +493,23 @@ static int da7210_init(struct da7210_priv *da7210)
415 /* FIXME 493 /* FIXME
416 * 494 *
417 * This driver use fixed value here 495 * This driver use fixed value here
496 * And below settings expects MCLK = 12.288MHz
497 *
498 * When you select different MCLK, please check...
499 * DA7210_PLL_DIV1 val
500 * DA7210_PLL_DIV2 val
501 * DA7210_PLL_DIV3 val
502 * DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
418 */ 503 */
419 504
420 /* 505 /*
506 * make sure that DA7210 use bypass mode before start up
507 */
508 da7210_write(codec, DA7210_STARTUP1, 0);
509 da7210_write(codec, DA7210_PLL_DIV3,
510 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
511
512 /*
421 * ADC settings 513 * ADC settings
422 */ 514 */
423 515
@@ -453,9 +545,28 @@ static int da7210_init(struct da7210_priv *da7210)
453 /* Diable PLL and bypass it */ 545 /* Diable PLL and bypass it */
454 da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); 546 da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
455 547
456 /* Bypass PLL and set MCLK freq rang to 10-20MHz */ 548 /*
457 da7210_write(codec, DA7210_PLL_DIV3, 549 * If 48kHz sound came, it use bypass mode,
550 * and when it is 44.1kHz, it use PLL.
551 *
552 * This time, this driver sets PLL always ON
553 * and controls bypass/PLL mode by switching
554 * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
555 * see da7210_hw_params
556 */
557 da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
558 da7210_write(codec, DA7210_PLL_DIV2, 0x99);
559 da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
458 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); 560 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
561 snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
562
563 /* As suggested by Dialog */
564 da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
565 da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
566 da7210_write(codec, DA7210_A_PLL1, 0x01);
567 da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
568 da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
569 da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
459 570
460 /* Activate all enabled subsystem */ 571 /* Activate all enabled subsystem */
461 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); 572 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index d2ff1cde6883..942f5dc30801 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -139,6 +139,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0),
139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), 139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
140 140
141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), 141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
142SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
142SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), 143SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
143 144
144SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), 145SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
@@ -604,8 +605,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
604 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); 605 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V);
605 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 606 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
606 /*select Line in as default input*/ 607 /*select Line in as default input*/
607 ssm2602_write(codec, SSM2602_APANA, 608 ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
608 APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC |
609 APANA_ENABLE_MIC_BOOST); 609 APANA_ENABLE_MIC_BOOST);
610 ssm2602_write(codec, SSM2602_PWR, 0); 610 ssm2602_write(codec, SSM2602_PWR, 0);
611 611
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index d50f1699ccb2..ee2e1e36d995 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -93,6 +93,8 @@ struct tlv320dac33_priv {
93 unsigned int nsample; /* burst read amount from host */ 93 unsigned int nsample; /* burst read amount from host */
94 u8 burst_bclkdiv; /* BCLK divider value in burst mode */ 94 u8 burst_bclkdiv; /* BCLK divider value in burst mode */
95 95
96 int keep_bclk; /* Keep the BCLK continuously running
97 * in FIFO modes */
96 enum dac33_state state; 98 enum dac33_state state;
97}; 99};
98 100
@@ -310,7 +312,8 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
310 if (power) 312 if (power)
311 reg |= DAC33_PDNALLB; 313 reg |= DAC33_PDNALLB;
312 else 314 else
313 reg &= ~DAC33_PDNALLB; 315 reg &= ~(DAC33_PDNALLB | DAC33_OSCPDNB |
316 DAC33_DACRPDNB | DAC33_DACLPDNB);
314 dac33_write(codec, DAC33_PWR_CTRL, reg); 317 dac33_write(codec, DAC33_PWR_CTRL, reg);
315} 318}
316 319
@@ -634,26 +637,6 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
634 return IRQ_HANDLED; 637 return IRQ_HANDLED;
635} 638}
636 639
637static void dac33_shutdown(struct snd_pcm_substream *substream,
638 struct snd_soc_dai *dai)
639{
640 struct snd_soc_pcm_runtime *rtd = substream->private_data;
641 struct snd_soc_device *socdev = rtd->socdev;
642 struct snd_soc_codec *codec = socdev->card->codec;
643 struct tlv320dac33_priv *dac33 = codec->private_data;
644 unsigned int pwr_ctrl;
645
646 /* Stop pending workqueue */
647 if (dac33->fifo_mode)
648 cancel_work_sync(&dac33->work);
649
650 mutex_lock(&dac33->mutex);
651 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
652 pwr_ctrl &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
653 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
654 mutex_unlock(&dac33->mutex);
655}
656
657static void dac33_oscwait(struct snd_soc_codec *codec) 640static void dac33_oscwait(struct snd_soc_codec *codec)
658{ 641{
659 int timeout = 20; 642 int timeout = 20;
@@ -751,6 +734,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
751 } 734 }
752 735
753 mutex_lock(&dac33->mutex); 736 mutex_lock(&dac33->mutex);
737 dac33_soft_power(codec, 0);
754 dac33_soft_power(codec, 1); 738 dac33_soft_power(codec, 1);
755 739
756 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); 740 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
@@ -821,7 +805,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
821 */ 805 */
822 fifoctrl_a &= ~DAC33_FBYPAS; 806 fifoctrl_a &= ~DAC33_FBYPAS;
823 fifoctrl_a &= ~DAC33_FAUTO; 807 fifoctrl_a &= ~DAC33_FAUTO;
824 aictrl_b &= ~DAC33_BCLKON; 808 if (dac33->keep_bclk)
809 aictrl_b |= DAC33_BCLKON;
810 else
811 aictrl_b &= ~DAC33_BCLKON;
825 break; 812 break;
826 case DAC33_FIFO_MODE7: 813 case DAC33_FIFO_MODE7:
827 /* 814 /*
@@ -832,7 +819,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
832 */ 819 */
833 fifoctrl_a &= ~DAC33_FBYPAS; 820 fifoctrl_a &= ~DAC33_FBYPAS;
834 fifoctrl_a |= DAC33_FAUTO; 821 fifoctrl_a |= DAC33_FAUTO;
835 aictrl_b &= ~DAC33_BCLKON; 822 if (dac33->keep_bclk)
823 aictrl_b |= DAC33_BCLKON;
824 else
825 aictrl_b &= ~DAC33_BCLKON;
836 break; 826 break;
837 default: 827 default:
838 /* 828 /*
@@ -1181,7 +1171,6 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
1181#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE 1171#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
1182 1172
1183static struct snd_soc_dai_ops dac33_dai_ops = { 1173static struct snd_soc_dai_ops dac33_dai_ops = {
1184 .shutdown = dac33_shutdown,
1185 .hw_params = dac33_hw_params, 1174 .hw_params = dac33_hw_params,
1186 .prepare = dac33_pcm_prepare, 1175 .prepare = dac33_pcm_prepare,
1187 .trigger = dac33_pcm_trigger, 1176 .trigger = dac33_pcm_trigger,
@@ -1249,6 +1238,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1249 1238
1250 dac33->power_gpio = pdata->power_gpio; 1239 dac33->power_gpio = pdata->power_gpio;
1251 dac33->burst_bclkdiv = pdata->burst_bclkdiv; 1240 dac33->burst_bclkdiv = pdata->burst_bclkdiv;
1241 dac33->keep_bclk = pdata->keep_bclk;
1252 dac33->irq = client->irq; 1242 dac33->irq = client->irq;
1253 dac33->nsample = NSAMPLE_MAX; 1243 dac33->nsample = NSAMPLE_MAX;
1254 /* Disable FIFO use by default */ 1244 /* Disable FIFO use by default */
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 6f5d4af20052..bf59b8a4d1d7 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -135,9 +135,11 @@ struct twl4030_priv {
135 135
136 unsigned int sysclk; 136 unsigned int sysclk;
137 137
138 /* Headset output state handling */ 138 /* Output (with associated amp) states */
139 unsigned int hsl_enabled; 139 u8 hsl_enabled, hsr_enabled;
140 unsigned int hsr_enabled; 140 u8 earpiece_enabled;
141 u8 predrivel_enabled, predriver_enabled;
142 u8 carkitl_enabled, carkitr_enabled;
141}; 143};
142 144
143/* 145/*
@@ -173,12 +175,47 @@ static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
173static int twl4030_write(struct snd_soc_codec *codec, 175static int twl4030_write(struct snd_soc_codec *codec,
174 unsigned int reg, unsigned int value) 176 unsigned int reg, unsigned int value)
175{ 177{
178 struct twl4030_priv *twl4030 = codec->private_data;
179 int write_to_reg = 0;
180
176 twl4030_write_reg_cache(codec, reg, value); 181 twl4030_write_reg_cache(codec, reg, value);
177 if (likely(reg < TWL4030_REG_SW_SHADOW)) 182 if (likely(reg < TWL4030_REG_SW_SHADOW)) {
178 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, 183 /* Decide if the given register can be written */
179 reg); 184 switch (reg) {
180 else 185 case TWL4030_REG_EAR_CTL:
181 return 0; 186 if (twl4030->earpiece_enabled)
187 write_to_reg = 1;
188 break;
189 case TWL4030_REG_PREDL_CTL:
190 if (twl4030->predrivel_enabled)
191 write_to_reg = 1;
192 break;
193 case TWL4030_REG_PREDR_CTL:
194 if (twl4030->predriver_enabled)
195 write_to_reg = 1;
196 break;
197 case TWL4030_REG_PRECKL_CTL:
198 if (twl4030->carkitl_enabled)
199 write_to_reg = 1;
200 break;
201 case TWL4030_REG_PRECKR_CTL:
202 if (twl4030->carkitr_enabled)
203 write_to_reg = 1;
204 break;
205 case TWL4030_REG_HS_GAIN_SET:
206 if (twl4030->hsl_enabled || twl4030->hsr_enabled)
207 write_to_reg = 1;
208 break;
209 default:
210 /* All other register can be written */
211 write_to_reg = 1;
212 break;
213 }
214 if (write_to_reg)
215 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
216 value, reg);
217 }
218 return 0;
182} 219}
183 220
184static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 221static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
@@ -525,26 +562,26 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
525 * Output PGA builder: 562 * Output PGA builder:
526 * Handle the muting and unmuting of the given output (turning off the 563 * Handle the muting and unmuting of the given output (turning off the
527 * amplifier associated with the output pin) 564 * amplifier associated with the output pin)
528 * On mute bypass the reg_cache and mute the volume 565 * On mute bypass the reg_cache and write 0 to the register
529 * On unmute: restore the register content 566 * On unmute: restore the register content from the reg_cache
530 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R 567 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R
531 */ 568 */
532#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ 569#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \
533static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ 570static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
534 struct snd_kcontrol *kcontrol, int event) \ 571 struct snd_kcontrol *kcontrol, int event) \
535{ \ 572{ \
536 u8 reg_val; \ 573 struct twl4030_priv *twl4030 = w->codec->private_data; \
537 \ 574 \
538 switch (event) { \ 575 switch (event) { \
539 case SND_SOC_DAPM_POST_PMU: \ 576 case SND_SOC_DAPM_POST_PMU: \
577 twl4030->pin_name##_enabled = 1; \
540 twl4030_write(w->codec, reg, \ 578 twl4030_write(w->codec, reg, \
541 twl4030_read_reg_cache(w->codec, reg)); \ 579 twl4030_read_reg_cache(w->codec, reg)); \
542 break; \ 580 break; \
543 case SND_SOC_DAPM_POST_PMD: \ 581 case SND_SOC_DAPM_POST_PMD: \
544 reg_val = twl4030_read_reg_cache(w->codec, reg); \ 582 twl4030->pin_name##_enabled = 0; \
545 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ 583 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \
546 reg_val & (~mask), \ 584 0, reg); \
547 reg); \
548 break; \ 585 break; \
549 } \ 586 } \
550 return 0; \ 587 return 0; \
@@ -664,7 +701,10 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
664 /* Headset ramp-up according to the TRM */ 701 /* Headset ramp-up according to the TRM */
665 hs_pop |= TWL4030_VMID_EN; 702 hs_pop |= TWL4030_VMID_EN;
666 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 703 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
667 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain); 704 /* Actually write to the register */
705 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
706 hs_gain,
707 TWL4030_REG_HS_GAIN_SET);
668 hs_pop |= TWL4030_RAMP_EN; 708 hs_pop |= TWL4030_RAMP_EN;
669 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 709 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
670 /* Wait ramp delay time + 1, so the VMID can settle */ 710 /* Wait ramp delay time + 1, so the VMID can settle */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
new file mode 100755
index 000000000000..0e4dce7de052
--- /dev/null
+++ b/sound/soc/codecs/twl6040.c
@@ -0,0 +1,1227 @@
1/*
2 * ALSA SoC TWL6040 codec driver
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/pm.h>
27#include <linux/i2c.h>
28#include <linux/gpio.h>
29#include <linux/platform_device.h>
30#include <linux/i2c/twl.h>
31
32#include <sound/core.h>
33#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35#include <sound/soc.h>
36#include <sound/soc-dapm.h>
37#include <sound/initval.h>
38#include <sound/tlv.h>
39
40#include "twl6040.h"
41
42#define TWL6040_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
43#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
44
45/* codec private data */
46struct twl6040_data {
47 struct snd_soc_codec codec;
48 int audpwron;
49 int naudint;
50 int codec_powered;
51 int pll;
52 int non_lp;
53 unsigned int sysclk;
54 struct snd_pcm_hw_constraint_list *sysclk_constraints;
55 struct completion ready;
56};
57
58/*
59 * twl6040 register cache & default register settings
60 */
61static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
62 0x00, /* not used 0x00 */
63 0x4B, /* TWL6040_ASICID (ro) 0x01 */
64 0x00, /* TWL6040_ASICREV (ro) 0x02 */
65 0x00, /* TWL6040_INTID 0x03 */
66 0x00, /* TWL6040_INTMR 0x04 */
67 0x00, /* TWL6040_NCPCTRL 0x05 */
68 0x00, /* TWL6040_LDOCTL 0x06 */
69 0x60, /* TWL6040_HPPLLCTL 0x07 */
70 0x00, /* TWL6040_LPPLLCTL 0x08 */
71 0x4A, /* TWL6040_LPPLLDIV 0x09 */
72 0x00, /* TWL6040_AMICBCTL 0x0A */
73 0x00, /* TWL6040_DMICBCTL 0x0B */
74 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */
75 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */
76 0x00, /* TWL6040_MICGAIN 0x0E */
77 0x1B, /* TWL6040_LINEGAIN 0x0F */
78 0x00, /* TWL6040_HSLCTL 0x10 */
79 0x00, /* TWL6040_HSRCTL 0x11 */
80 0x00, /* TWL6040_HSGAIN 0x12 */
81 0x00, /* TWL6040_EARCTL 0x13 */
82 0x00, /* TWL6040_HFLCTL 0x14 */
83 0x00, /* TWL6040_HFLGAIN 0x15 */
84 0x00, /* TWL6040_HFRCTL 0x16 */
85 0x00, /* TWL6040_HFRGAIN 0x17 */
86 0x00, /* TWL6040_VIBCTLL 0x18 */
87 0x00, /* TWL6040_VIBDATL 0x19 */
88 0x00, /* TWL6040_VIBCTLR 0x1A */
89 0x00, /* TWL6040_VIBDATR 0x1B */
90 0x00, /* TWL6040_HKCTL1 0x1C */
91 0x00, /* TWL6040_HKCTL2 0x1D */
92 0x00, /* TWL6040_GPOCTL 0x1E */
93 0x00, /* TWL6040_ALB 0x1F */
94 0x00, /* TWL6040_DLB 0x20 */
95 0x00, /* not used 0x21 */
96 0x00, /* not used 0x22 */
97 0x00, /* not used 0x23 */
98 0x00, /* not used 0x24 */
99 0x00, /* not used 0x25 */
100 0x00, /* not used 0x26 */
101 0x00, /* not used 0x27 */
102 0x00, /* TWL6040_TRIM1 0x28 */
103 0x00, /* TWL6040_TRIM2 0x29 */
104 0x00, /* TWL6040_TRIM3 0x2A */
105 0x00, /* TWL6040_HSOTRIM 0x2B */
106 0x00, /* TWL6040_HFOTRIM 0x2C */
107 0x09, /* TWL6040_ACCCTL 0x2D */
108 0x00, /* TWL6040_STATUS (ro) 0x2E */
109};
110
111/*
112 * twl6040 vio/gnd registers:
113 * registers under vio/gnd supply can be accessed
114 * before the power-up sequence, after NRESPWRON goes high
115 */
116static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
117 TWL6040_REG_ASICID,
118 TWL6040_REG_ASICREV,
119 TWL6040_REG_INTID,
120 TWL6040_REG_INTMR,
121 TWL6040_REG_NCPCTL,
122 TWL6040_REG_LDOCTL,
123 TWL6040_REG_AMICBCTL,
124 TWL6040_REG_DMICBCTL,
125 TWL6040_REG_HKCTL1,
126 TWL6040_REG_HKCTL2,
127 TWL6040_REG_GPOCTL,
128 TWL6040_REG_TRIM1,
129 TWL6040_REG_TRIM2,
130 TWL6040_REG_TRIM3,
131 TWL6040_REG_HSOTRIM,
132 TWL6040_REG_HFOTRIM,
133 TWL6040_REG_ACCCTL,
134 TWL6040_REG_STATUS,
135};
136
137/*
138 * twl6040 vdd/vss registers:
139 * registers under vdd/vss supplies can only be accessed
140 * after the power-up sequence
141 */
142static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
143 TWL6040_REG_HPPLLCTL,
144 TWL6040_REG_LPPLLCTL,
145 TWL6040_REG_LPPLLDIV,
146 TWL6040_REG_MICLCTL,
147 TWL6040_REG_MICRCTL,
148 TWL6040_REG_MICGAIN,
149 TWL6040_REG_LINEGAIN,
150 TWL6040_REG_HSLCTL,
151 TWL6040_REG_HSRCTL,
152 TWL6040_REG_HSGAIN,
153 TWL6040_REG_EARCTL,
154 TWL6040_REG_HFLCTL,
155 TWL6040_REG_HFLGAIN,
156 TWL6040_REG_HFRCTL,
157 TWL6040_REG_HFRGAIN,
158 TWL6040_REG_VIBCTLL,
159 TWL6040_REG_VIBDATL,
160 TWL6040_REG_VIBCTLR,
161 TWL6040_REG_VIBDATR,
162 TWL6040_REG_ALB,
163 TWL6040_REG_DLB,
164};
165
166/*
167 * read twl6040 register cache
168 */
169static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec,
170 unsigned int reg)
171{
172 u8 *cache = codec->reg_cache;
173
174 if (reg >= TWL6040_CACHEREGNUM)
175 return -EIO;
176
177 return cache[reg];
178}
179
180/*
181 * write twl6040 register cache
182 */
183static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
184 u8 reg, u8 value)
185{
186 u8 *cache = codec->reg_cache;
187
188 if (reg >= TWL6040_CACHEREGNUM)
189 return;
190 cache[reg] = value;
191}
192
193/*
194 * read from twl6040 hardware register
195 */
196static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
197 unsigned int reg)
198{
199 u8 value;
200
201 if (reg >= TWL6040_CACHEREGNUM)
202 return -EIO;
203
204 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg);
205 twl6040_write_reg_cache(codec, reg, value);
206
207 return value;
208}
209
210/*
211 * write to the twl6040 register space
212 */
213static int twl6040_write(struct snd_soc_codec *codec,
214 unsigned int reg, unsigned int value)
215{
216 if (reg >= TWL6040_CACHEREGNUM)
217 return -EIO;
218
219 twl6040_write_reg_cache(codec, reg, value);
220 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
221}
222
223static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
224{
225 u8 *cache = codec->reg_cache;
226 int reg, i;
227
228 /* allow registers to be accessed by i2c */
229 twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
230
231 for (i = 0; i < TWL6040_VIOREGNUM; i++) {
232 reg = twl6040_vio_reg[i];
233 /* skip read-only registers (ASICID, ASICREV, STATUS) */
234 switch (reg) {
235 case TWL6040_REG_ASICID:
236 case TWL6040_REG_ASICREV:
237 case TWL6040_REG_STATUS:
238 continue;
239 default:
240 break;
241 }
242 twl6040_write(codec, reg, cache[reg]);
243 }
244}
245
246static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
247{
248 u8 *cache = codec->reg_cache;
249 int reg, i;
250
251 for (i = 0; i < TWL6040_VDDREGNUM; i++) {
252 reg = twl6040_vdd_reg[i];
253 twl6040_write(codec, reg, cache[reg]);
254 }
255}
256
257/* twl6040 codec manual power-up sequence */
258static void twl6040_power_up(struct snd_soc_codec *codec)
259{
260 u8 ncpctl, ldoctl, lppllctl, accctl;
261
262 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
263 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
264 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
265 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
266
267 /* enable reference system */
268 ldoctl |= TWL6040_REFENA;
269 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
270 msleep(10);
271 /* enable internal oscillator */
272 ldoctl |= TWL6040_OSCENA;
273 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
274 udelay(10);
275 /* enable high-side ldo */
276 ldoctl |= TWL6040_HSLDOENA;
277 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
278 udelay(244);
279 /* enable negative charge pump */
280 ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
281 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
282 udelay(488);
283 /* enable low-side ldo */
284 ldoctl |= TWL6040_LSLDOENA;
285 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
286 udelay(244);
287 /* enable low-power pll */
288 lppllctl |= TWL6040_LPLLENA;
289 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
290 /* reset state machine */
291 accctl |= TWL6040_RESETSPLIT;
292 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
293 mdelay(5);
294 accctl &= ~TWL6040_RESETSPLIT;
295 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
296 /* disable internal oscillator */
297 ldoctl &= ~TWL6040_OSCENA;
298 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
299}
300
301/* twl6040 codec manual power-down sequence */
302static void twl6040_power_down(struct snd_soc_codec *codec)
303{
304 u8 ncpctl, ldoctl, lppllctl, accctl;
305
306 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
307 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
308 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
309 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
310
311 /* enable internal oscillator */
312 ldoctl |= TWL6040_OSCENA;
313 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
314 udelay(10);
315 /* disable low-power pll */
316 lppllctl &= ~TWL6040_LPLLENA;
317 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
318 /* disable low-side ldo */
319 ldoctl &= ~TWL6040_LSLDOENA;
320 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
321 udelay(244);
322 /* disable negative charge pump */
323 ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
324 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
325 udelay(488);
326 /* disable high-side ldo */
327 ldoctl &= ~TWL6040_HSLDOENA;
328 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
329 udelay(244);
330 /* disable internal oscillator */
331 ldoctl &= ~TWL6040_OSCENA;
332 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
333 /* disable reference system */
334 ldoctl &= ~TWL6040_REFENA;
335 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
336 msleep(10);
337}
338
339/* set headset dac and driver power mode */
340static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
341{
342 int hslctl, hsrctl;
343 int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
344
345 hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
346 hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
347
348 if (high_perf) {
349 hslctl &= ~mask;
350 hsrctl &= ~mask;
351 } else {
352 hslctl |= mask;
353 hsrctl |= mask;
354 }
355
356 twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
357 twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
358
359 return 0;
360}
361
362static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
363 struct snd_kcontrol *kcontrol, int event)
364{
365 struct snd_soc_codec *codec = w->codec;
366 struct twl6040_data *priv = codec->private_data;
367
368 if (SND_SOC_DAPM_EVENT_ON(event))
369 priv->non_lp++;
370 else
371 priv->non_lp--;
372
373 return 0;
374}
375
376/* audio interrupt handler */
377static irqreturn_t twl6040_naudint_handler(int irq, void *data)
378{
379 struct snd_soc_codec *codec = data;
380 struct twl6040_data *priv = codec->private_data;
381 u8 intid;
382
383 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
384
385 switch (intid) {
386 case TWL6040_THINT:
387 dev_alert(codec->dev, "die temp over-limit detection\n");
388 break;
389 case TWL6040_PLUGINT:
390 case TWL6040_UNPLUGINT:
391 case TWL6040_HOOKINT:
392 break;
393 case TWL6040_HFINT:
394 dev_alert(codec->dev, "hf drivers over current detection\n");
395 break;
396 case TWL6040_VIBINT:
397 dev_alert(codec->dev, "vib drivers over current detection\n");
398 break;
399 case TWL6040_READYINT:
400 complete(&priv->ready);
401 break;
402 default:
403 dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
404 break;
405 }
406
407 return IRQ_HANDLED;
408}
409
410/*
411 * MICATT volume control:
412 * from -6 to 0 dB in 6 dB steps
413 */
414static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
415
416/*
417 * MICGAIN volume control:
418 * from 6 to 30 dB in 6 dB steps
419 */
420static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
421
422/*
423 * HSGAIN volume control:
424 * from -30 to 0 dB in 2 dB steps
425 */
426static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
427
428/*
429 * HFGAIN volume control:
430 * from -52 to 6 dB in 2 dB steps
431 */
432static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
433
434/* Left analog microphone selection */
435static const char *twl6040_amicl_texts[] =
436 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
437
438/* Right analog microphone selection */
439static const char *twl6040_amicr_texts[] =
440 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
441
442static const struct soc_enum twl6040_enum[] = {
443 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 3, twl6040_amicl_texts),
444 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 3, twl6040_amicr_texts),
445};
446
447static const struct snd_kcontrol_new amicl_control =
448 SOC_DAPM_ENUM("Route", twl6040_enum[0]);
449
450static const struct snd_kcontrol_new amicr_control =
451 SOC_DAPM_ENUM("Route", twl6040_enum[1]);
452
453/* Headset DAC playback switches */
454static const struct snd_kcontrol_new hsdacl_switch_controls =
455 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 5, 1, 0);
456
457static const struct snd_kcontrol_new hsdacr_switch_controls =
458 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 5, 1, 0);
459
460/* Handsfree DAC playback switches */
461static const struct snd_kcontrol_new hfdacl_switch_controls =
462 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 2, 1, 0);
463
464static const struct snd_kcontrol_new hfdacr_switch_controls =
465 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0);
466
467/* Headset driver switches */
468static const struct snd_kcontrol_new hsl_driver_switch_controls =
469 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 2, 1, 0);
470
471static const struct snd_kcontrol_new hsr_driver_switch_controls =
472 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 2, 1, 0);
473
474/* Handsfree driver switches */
475static const struct snd_kcontrol_new hfl_driver_switch_controls =
476 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 4, 1, 0);
477
478static const struct snd_kcontrol_new hfr_driver_switch_controls =
479 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0);
480
481static const struct snd_kcontrol_new twl6040_snd_controls[] = {
482 /* Capture gains */
483 SOC_DOUBLE_TLV("Capture Preamplifier Volume",
484 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
485 SOC_DOUBLE_TLV("Capture Volume",
486 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
487
488 /* Playback gains */
489 SOC_DOUBLE_TLV("Headset Playback Volume",
490 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
491 SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
492 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
493
494};
495
496static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
497 /* Inputs */
498 SND_SOC_DAPM_INPUT("MAINMIC"),
499 SND_SOC_DAPM_INPUT("HSMIC"),
500 SND_SOC_DAPM_INPUT("SUBMIC"),
501 SND_SOC_DAPM_INPUT("AFML"),
502 SND_SOC_DAPM_INPUT("AFMR"),
503
504 /* Outputs */
505 SND_SOC_DAPM_OUTPUT("HSOL"),
506 SND_SOC_DAPM_OUTPUT("HSOR"),
507 SND_SOC_DAPM_OUTPUT("HFL"),
508 SND_SOC_DAPM_OUTPUT("HFR"),
509
510 /* Analog input muxes for the capture amplifiers */
511 SND_SOC_DAPM_MUX("Analog Left Capture Route",
512 SND_SOC_NOPM, 0, 0, &amicl_control),
513 SND_SOC_DAPM_MUX("Analog Right Capture Route",
514 SND_SOC_NOPM, 0, 0, &amicr_control),
515
516 /* Analog capture PGAs */
517 SND_SOC_DAPM_PGA("MicAmpL",
518 TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
519 SND_SOC_DAPM_PGA("MicAmpR",
520 TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
521
522 /* ADCs */
523 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
524 TWL6040_REG_MICLCTL, 2, 0),
525 SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
526 TWL6040_REG_MICRCTL, 2, 0),
527
528 /* Microphone bias */
529 SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
530 TWL6040_REG_AMICBCTL, 0, 0),
531 SND_SOC_DAPM_MICBIAS("Main Mic Bias",
532 TWL6040_REG_AMICBCTL, 4, 0),
533 SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
534 TWL6040_REG_DMICBCTL, 0, 0),
535 SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
536 TWL6040_REG_DMICBCTL, 4, 0),
537
538 /* DACs */
539 SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback",
540 TWL6040_REG_HSLCTL, 0, 0),
541 SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback",
542 TWL6040_REG_HSRCTL, 0, 0),
543 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
544 TWL6040_REG_HFLCTL, 0, 0,
545 twl6040_power_mode_event,
546 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
547 SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
548 TWL6040_REG_HFRCTL, 0, 0,
549 twl6040_power_mode_event,
550 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
551
552 /* Analog playback switches */
553 SND_SOC_DAPM_SWITCH("HSDAC Left Playback",
554 SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls),
555 SND_SOC_DAPM_SWITCH("HSDAC Right Playback",
556 SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls),
557 SND_SOC_DAPM_SWITCH("HFDAC Left Playback",
558 SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls),
559 SND_SOC_DAPM_SWITCH("HFDAC Right Playback",
560 SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls),
561
562 SND_SOC_DAPM_SWITCH("Headset Left Driver",
563 SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls),
564 SND_SOC_DAPM_SWITCH("Headset Right Driver",
565 SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls),
566 SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver",
567 SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls,
568 twl6040_power_mode_event,
569 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
570 SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver",
571 SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls,
572 twl6040_power_mode_event,
573 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
574
575 /* Analog playback PGAs */
576 SND_SOC_DAPM_PGA("HFDAC Left PGA",
577 TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
578 SND_SOC_DAPM_PGA("HFDAC Right PGA",
579 TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
580
581};
582
583static const struct snd_soc_dapm_route intercon[] = {
584 /* Capture path */
585 {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
586 {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
587 {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
588
589 {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
590 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
591 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
592
593 {"MicAmpL", NULL, "Analog Left Capture Route"},
594 {"MicAmpR", NULL, "Analog Right Capture Route"},
595
596 {"ADC Left", NULL, "MicAmpL"},
597 {"ADC Right", NULL, "MicAmpR"},
598
599 /* Headset playback path */
600 {"HSDAC Left Playback", "Switch", "HSDAC Left"},
601 {"HSDAC Right Playback", "Switch", "HSDAC Right"},
602
603 {"Headset Left Driver", "Switch", "HSDAC Left Playback"},
604 {"Headset Right Driver", "Switch", "HSDAC Right Playback"},
605
606 {"HSOL", NULL, "Headset Left Driver"},
607 {"HSOR", NULL, "Headset Right Driver"},
608
609 /* Handsfree playback path */
610 {"HFDAC Left Playback", "Switch", "HFDAC Left"},
611 {"HFDAC Right Playback", "Switch", "HFDAC Right"},
612
613 {"HFDAC Left PGA", NULL, "HFDAC Left Playback"},
614 {"HFDAC Right PGA", NULL, "HFDAC Right Playback"},
615
616 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
617 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
618
619 {"HFL", NULL, "Handsfree Left Driver"},
620 {"HFR", NULL, "Handsfree Right Driver"},
621};
622
623static int twl6040_add_widgets(struct snd_soc_codec *codec)
624{
625 snd_soc_dapm_new_controls(codec, twl6040_dapm_widgets,
626 ARRAY_SIZE(twl6040_dapm_widgets));
627
628 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
629
630 snd_soc_dapm_new_widgets(codec);
631
632 return 0;
633}
634
635static int twl6040_power_up_completion(struct snd_soc_codec *codec,
636 int naudint)
637{
638 struct twl6040_data *priv = codec->private_data;
639 int time_left;
640 u8 intid;
641
642 time_left = wait_for_completion_timeout(&priv->ready,
643 msecs_to_jiffies(48));
644
645 if (!time_left) {
646 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid,
647 TWL6040_REG_INTID);
648 if (!(intid & TWL6040_READYINT)) {
649 dev_err(codec->dev, "timeout waiting for READYINT\n");
650 return -ETIMEDOUT;
651 }
652 }
653
654 priv->codec_powered = 1;
655
656 return 0;
657}
658
659static int twl6040_set_bias_level(struct snd_soc_codec *codec,
660 enum snd_soc_bias_level level)
661{
662 struct twl6040_data *priv = codec->private_data;
663 int audpwron = priv->audpwron;
664 int naudint = priv->naudint;
665 int ret;
666
667 switch (level) {
668 case SND_SOC_BIAS_ON:
669 break;
670 case SND_SOC_BIAS_PREPARE:
671 break;
672 case SND_SOC_BIAS_STANDBY:
673 if (priv->codec_powered)
674 break;
675
676 if (gpio_is_valid(audpwron)) {
677 /* use AUDPWRON line */
678 gpio_set_value(audpwron, 1);
679
680 /* wait for power-up completion */
681 ret = twl6040_power_up_completion(codec, naudint);
682 if (ret)
683 return ret;
684
685 /* sync registers updated during power-up sequence */
686 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
687 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
688 twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
689 } else {
690 /* use manual power-up sequence */
691 twl6040_power_up(codec);
692 priv->codec_powered = 1;
693 }
694
695 /* initialize vdd/vss registers with reg_cache */
696 twl6040_init_vdd_regs(codec);
697 break;
698 case SND_SOC_BIAS_OFF:
699 if (!priv->codec_powered)
700 break;
701
702 if (gpio_is_valid(audpwron)) {
703 /* use AUDPWRON line */
704 gpio_set_value(audpwron, 0);
705
706 /* power-down sequence latency */
707 udelay(500);
708
709 /* sync registers updated during power-down sequence */
710 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
711 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
712 twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
713 0x00);
714 } else {
715 /* use manual power-down sequence */
716 twl6040_power_down(codec);
717 }
718
719 priv->codec_powered = 0;
720 break;
721 }
722
723 codec->bias_level = level;
724
725 return 0;
726}
727
728/* set of rates for each pll: low-power and high-performance */
729
730static unsigned int lp_rates[] = {
731 88200,
732 96000,
733};
734
735static struct snd_pcm_hw_constraint_list lp_constraints = {
736 .count = ARRAY_SIZE(lp_rates),
737 .list = lp_rates,
738};
739
740static unsigned int hp_rates[] = {
741 96000,
742};
743
744static struct snd_pcm_hw_constraint_list hp_constraints = {
745 .count = ARRAY_SIZE(hp_rates),
746 .list = hp_rates,
747};
748
749static int twl6040_startup(struct snd_pcm_substream *substream,
750 struct snd_soc_dai *dai)
751{
752 struct snd_soc_pcm_runtime *rtd = substream->private_data;
753 struct snd_soc_device *socdev = rtd->socdev;
754 struct snd_soc_codec *codec = socdev->card->codec;
755 struct twl6040_data *priv = codec->private_data;
756
757 if (!priv->sysclk) {
758 dev_err(codec->dev,
759 "no mclk configured, call set_sysclk() on init\n");
760 return -EINVAL;
761 }
762
763 /*
764 * capture is not supported at 17.64 MHz,
765 * it's reserved for headset low-power playback scenario
766 */
767 if ((priv->sysclk == 17640000) && substream->stream) {
768 dev_err(codec->dev,
769 "capture mode is not supported at %dHz\n",
770 priv->sysclk);
771 return -EINVAL;
772 }
773
774 snd_pcm_hw_constraint_list(substream->runtime, 0,
775 SNDRV_PCM_HW_PARAM_RATE,
776 priv->sysclk_constraints);
777
778 return 0;
779}
780
781static int twl6040_hw_params(struct snd_pcm_substream *substream,
782 struct snd_pcm_hw_params *params,
783 struct snd_soc_dai *dai)
784{
785 struct snd_soc_pcm_runtime *rtd = substream->private_data;
786 struct snd_soc_device *socdev = rtd->socdev;
787 struct snd_soc_codec *codec = socdev->card->codec;
788 struct twl6040_data *priv = codec->private_data;
789 u8 lppllctl;
790 int rate;
791
792 /* nothing to do for high-perf pll, it supports only 48 kHz */
793 if (priv->pll == TWL6040_HPPLL_ID)
794 return 0;
795
796 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
797
798 rate = params_rate(params);
799 switch (rate) {
800 case 88200:
801 lppllctl |= TWL6040_LPLLFIN;
802 priv->sysclk = 17640000;
803 break;
804 case 96000:
805 lppllctl &= ~TWL6040_LPLLFIN;
806 priv->sysclk = 19200000;
807 break;
808 default:
809 dev_err(codec->dev, "unsupported rate %d\n", rate);
810 return -EINVAL;
811 }
812
813 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
814
815 return 0;
816}
817
818static int twl6040_trigger(struct snd_pcm_substream *substream,
819 int cmd, struct snd_soc_dai *dai)
820{
821 struct snd_soc_pcm_runtime *rtd = substream->private_data;
822 struct snd_soc_device *socdev = rtd->socdev;
823 struct snd_soc_codec *codec = socdev->card->codec;
824 struct twl6040_data *priv = codec->private_data;
825
826 switch (cmd) {
827 case SNDRV_PCM_TRIGGER_START:
828 case SNDRV_PCM_TRIGGER_RESUME:
829 /*
830 * low-power playback mode is restricted
831 * for headset path only
832 */
833 if ((priv->sysclk == 17640000) && priv->non_lp) {
834 dev_err(codec->dev,
835 "some enabled paths aren't supported at %dHz\n",
836 priv->sysclk);
837 return -EPERM;
838 }
839 break;
840 default:
841 break;
842 }
843
844 return 0;
845}
846
847static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
848 int clk_id, unsigned int freq, int dir)
849{
850 struct snd_soc_codec *codec = codec_dai->codec;
851 struct twl6040_data *priv = codec->private_data;
852 u8 hppllctl, lppllctl;
853
854 hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
855 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
856
857 switch (clk_id) {
858 case TWL6040_SYSCLK_SEL_LPPLL:
859 switch (freq) {
860 case 32768:
861 /* headset dac and driver must be in low-power mode */
862 headset_power_mode(codec, 0);
863
864 /* clk32k input requires low-power pll */
865 lppllctl |= TWL6040_LPLLENA;
866 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
867 mdelay(5);
868 lppllctl &= ~TWL6040_HPLLSEL;
869 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
870 hppllctl &= ~TWL6040_HPLLENA;
871 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
872 break;
873 default:
874 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
875 return -EINVAL;
876 }
877
878 /* lppll divider */
879 switch (priv->sysclk) {
880 case 17640000:
881 lppllctl |= TWL6040_LPLLFIN;
882 break;
883 case 19200000:
884 lppllctl &= ~TWL6040_LPLLFIN;
885 break;
886 default:
887 /* sysclk not yet configured */
888 lppllctl &= ~TWL6040_LPLLFIN;
889 priv->sysclk = 19200000;
890 break;
891 }
892
893 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
894
895 priv->pll = TWL6040_LPPLL_ID;
896 priv->sysclk_constraints = &lp_constraints;
897 break;
898 case TWL6040_SYSCLK_SEL_HPPLL:
899 hppllctl &= ~TWL6040_MCLK_MSK;
900
901 switch (freq) {
902 case 12000000:
903 /* mclk input, pll enabled */
904 hppllctl |= TWL6040_MCLK_12000KHZ |
905 TWL6040_HPLLSQRBP |
906 TWL6040_HPLLENA;
907 break;
908 case 19200000:
909 /* mclk input, pll disabled */
910 hppllctl |= TWL6040_MCLK_19200KHZ |
911 TWL6040_HPLLSQRBP |
912 TWL6040_HPLLBP;
913 break;
914 case 26000000:
915 /* mclk input, pll enabled */
916 hppllctl |= TWL6040_MCLK_26000KHZ |
917 TWL6040_HPLLSQRBP |
918 TWL6040_HPLLENA;
919 break;
920 case 38400000:
921 /* clk slicer, pll disabled */
922 hppllctl |= TWL6040_MCLK_38400KHZ |
923 TWL6040_HPLLSQRENA |
924 TWL6040_HPLLBP;
925 break;
926 default:
927 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
928 return -EINVAL;
929 }
930
931 /* headset dac and driver must be in high-performance mode */
932 headset_power_mode(codec, 1);
933
934 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
935 udelay(500);
936 lppllctl |= TWL6040_HPLLSEL;
937 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
938 lppllctl &= ~TWL6040_LPLLENA;
939 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
940
941 /* high-performance pll can provide only 19.2 MHz */
942 priv->pll = TWL6040_HPPLL_ID;
943 priv->sysclk = 19200000;
944 priv->sysclk_constraints = &hp_constraints;
945 break;
946 default:
947 dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
948 return -EINVAL;
949 }
950
951 return 0;
952}
953
954static struct snd_soc_dai_ops twl6040_dai_ops = {
955 .startup = twl6040_startup,
956 .hw_params = twl6040_hw_params,
957 .trigger = twl6040_trigger,
958 .set_sysclk = twl6040_set_dai_sysclk,
959};
960
961struct snd_soc_dai twl6040_dai = {
962 .name = "twl6040",
963 .playback = {
964 .stream_name = "Playback",
965 .channels_min = 1,
966 .channels_max = 4,
967 .rates = TWL6040_RATES,
968 .formats = TWL6040_FORMATS,
969 },
970 .capture = {
971 .stream_name = "Capture",
972 .channels_min = 1,
973 .channels_max = 2,
974 .rates = TWL6040_RATES,
975 .formats = TWL6040_FORMATS,
976 },
977 .ops = &twl6040_dai_ops,
978};
979EXPORT_SYMBOL_GPL(twl6040_dai);
980
981#ifdef CONFIG_PM
982static int twl6040_suspend(struct platform_device *pdev, pm_message_t state)
983{
984 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
985 struct snd_soc_codec *codec = socdev->card->codec;
986
987 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
988
989 return 0;
990}
991
992static int twl6040_resume(struct platform_device *pdev)
993{
994 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
995 struct snd_soc_codec *codec = socdev->card->codec;
996
997 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
998 twl6040_set_bias_level(codec, codec->suspend_bias_level);
999
1000 return 0;
1001}
1002#else
1003#define twl6040_suspend NULL
1004#define twl6040_resume NULL
1005#endif
1006
1007static struct snd_soc_codec *twl6040_codec;
1008
1009static int twl6040_probe(struct platform_device *pdev)
1010{
1011 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1012 struct snd_soc_codec *codec;
1013 int ret = 0;
1014
1015 BUG_ON(!twl6040_codec);
1016
1017 codec = twl6040_codec;
1018 socdev->card->codec = codec;
1019
1020 /* register pcms */
1021 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1022 if (ret < 0) {
1023 dev_err(&pdev->dev, "failed to create pcms\n");
1024 return ret;
1025 }
1026
1027 snd_soc_add_controls(codec, twl6040_snd_controls,
1028 ARRAY_SIZE(twl6040_snd_controls));
1029 twl6040_add_widgets(codec);
1030
1031 if (ret < 0) {
1032 dev_err(&pdev->dev, "failed to register card\n");
1033 goto card_err;
1034 }
1035
1036 return ret;
1037
1038card_err:
1039 snd_soc_free_pcms(socdev);
1040 snd_soc_dapm_free(socdev);
1041 return ret;
1042}
1043
1044static int twl6040_remove(struct platform_device *pdev)
1045{
1046 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1047 struct snd_soc_codec *codec = socdev->card->codec;
1048
1049 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1050 snd_soc_free_pcms(socdev);
1051 snd_soc_dapm_free(socdev);
1052 kfree(codec);
1053
1054 return 0;
1055}
1056
1057struct snd_soc_codec_device soc_codec_dev_twl6040 = {
1058 .probe = twl6040_probe,
1059 .remove = twl6040_remove,
1060 .suspend = twl6040_suspend,
1061 .resume = twl6040_resume,
1062};
1063EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
1064
1065static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1066{
1067 struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
1068 struct snd_soc_codec *codec;
1069 struct twl6040_data *priv;
1070 int audpwron, naudint;
1071 int ret = 0;
1072
1073 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1074 if (priv == NULL)
1075 return -ENOMEM;
1076
1077 if (twl_codec) {
1078 audpwron = twl_codec->audpwron_gpio;
1079 naudint = twl_codec->naudint_irq;
1080 } else {
1081 audpwron = -EINVAL;
1082 naudint = 0;
1083 }
1084
1085 priv->audpwron = audpwron;
1086 priv->naudint = naudint;
1087
1088 codec = &priv->codec;
1089 codec->dev = &pdev->dev;
1090 twl6040_dai.dev = &pdev->dev;
1091
1092 codec->name = "twl6040";
1093 codec->owner = THIS_MODULE;
1094 codec->read = twl6040_read_reg_cache;
1095 codec->write = twl6040_write;
1096 codec->set_bias_level = twl6040_set_bias_level;
1097 codec->private_data = priv;
1098 codec->dai = &twl6040_dai;
1099 codec->num_dai = 1;
1100 codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
1101 codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
1102 GFP_KERNEL);
1103 if (codec->reg_cache == NULL) {
1104 ret = -ENOMEM;
1105 goto cache_err;
1106 }
1107
1108 mutex_init(&codec->mutex);
1109 INIT_LIST_HEAD(&codec->dapm_widgets);
1110 INIT_LIST_HEAD(&codec->dapm_paths);
1111 init_completion(&priv->ready);
1112
1113 if (gpio_is_valid(audpwron)) {
1114 ret = gpio_request(audpwron, "audpwron");
1115 if (ret)
1116 goto gpio1_err;
1117
1118 ret = gpio_direction_output(audpwron, 0);
1119 if (ret)
1120 goto gpio2_err;
1121
1122 priv->codec_powered = 0;
1123 }
1124
1125 if (naudint) {
1126 /* audio interrupt */
1127 ret = request_threaded_irq(naudint, NULL,
1128 twl6040_naudint_handler,
1129 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
1130 "twl6040_codec", codec);
1131 if (ret)
1132 goto gpio2_err;
1133 } else {
1134 if (gpio_is_valid(audpwron)) {
1135 /* enable only codec ready interrupt */
1136 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1137 ~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
1138 } else {
1139 /* no interrupts at all */
1140 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1141 TWL6040_ALLINT_MSK);
1142 }
1143 }
1144
1145 /* init vio registers */
1146 twl6040_init_vio_regs(codec);
1147
1148 /* power on device */
1149 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1150 if (ret)
1151 goto irq_err;
1152
1153 ret = snd_soc_register_codec(codec);
1154 if (ret)
1155 goto reg_err;
1156
1157 twl6040_codec = codec;
1158
1159 ret = snd_soc_register_dai(&twl6040_dai);
1160 if (ret)
1161 goto dai_err;
1162
1163 return 0;
1164
1165dai_err:
1166 snd_soc_unregister_codec(codec);
1167 twl6040_codec = NULL;
1168reg_err:
1169 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1170irq_err:
1171 if (naudint)
1172 free_irq(naudint, codec);
1173gpio2_err:
1174 if (gpio_is_valid(audpwron))
1175 gpio_free(audpwron);
1176gpio1_err:
1177 kfree(codec->reg_cache);
1178cache_err:
1179 kfree(priv);
1180 return ret;
1181}
1182
1183static int __devexit twl6040_codec_remove(struct platform_device *pdev)
1184{
1185 struct twl6040_data *priv = twl6040_codec->private_data;
1186 int audpwron = priv->audpwron;
1187 int naudint = priv->naudint;
1188
1189 if (gpio_is_valid(audpwron))
1190 gpio_free(audpwron);
1191
1192 if (naudint)
1193 free_irq(naudint, twl6040_codec);
1194
1195 snd_soc_unregister_dai(&twl6040_dai);
1196 snd_soc_unregister_codec(twl6040_codec);
1197
1198 kfree(twl6040_codec);
1199 twl6040_codec = NULL;
1200
1201 return 0;
1202}
1203
1204static struct platform_driver twl6040_codec_driver = {
1205 .driver = {
1206 .name = "twl6040_codec",
1207 .owner = THIS_MODULE,
1208 },
1209 .probe = twl6040_codec_probe,
1210 .remove = __devexit_p(twl6040_codec_remove),
1211};
1212
1213static int __init twl6040_codec_init(void)
1214{
1215 return platform_driver_register(&twl6040_codec_driver);
1216}
1217module_init(twl6040_codec_init);
1218
1219static void __exit twl6040_codec_exit(void)
1220{
1221 platform_driver_unregister(&twl6040_codec_driver);
1222}
1223module_exit(twl6040_codec_exit);
1224
1225MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1226MODULE_AUTHOR("Misael Lopez Cruz");
1227MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
new file mode 100644
index 000000000000..c472070a1da2
--- /dev/null
+++ b/sound/soc/codecs/twl6040.h
@@ -0,0 +1,141 @@
1/*
2 * ALSA SoC TWL6040 codec driver
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __TWL6040_H__
23#define __TWL6040_H__
24
25#define TWL6040_REG_ASICID 0x01
26#define TWL6040_REG_ASICREV 0x02
27#define TWL6040_REG_INTID 0x03
28#define TWL6040_REG_INTMR 0x04
29#define TWL6040_REG_NCPCTL 0x05
30#define TWL6040_REG_LDOCTL 0x06
31#define TWL6040_REG_HPPLLCTL 0x07
32#define TWL6040_REG_LPPLLCTL 0x08
33#define TWL6040_REG_LPPLLDIV 0x09
34#define TWL6040_REG_AMICBCTL 0x0A
35#define TWL6040_REG_DMICBCTL 0x0B
36#define TWL6040_REG_MICLCTL 0x0C
37#define TWL6040_REG_MICRCTL 0x0D
38#define TWL6040_REG_MICGAIN 0x0E
39#define TWL6040_REG_LINEGAIN 0x0F
40#define TWL6040_REG_HSLCTL 0x10
41#define TWL6040_REG_HSRCTL 0x11
42#define TWL6040_REG_HSGAIN 0x12
43#define TWL6040_REG_EARCTL 0x13
44#define TWL6040_REG_HFLCTL 0x14
45#define TWL6040_REG_HFLGAIN 0x15
46#define TWL6040_REG_HFRCTL 0x16
47#define TWL6040_REG_HFRGAIN 0x17
48#define TWL6040_REG_VIBCTLL 0x18
49#define TWL6040_REG_VIBDATL 0x19
50#define TWL6040_REG_VIBCTLR 0x1A
51#define TWL6040_REG_VIBDATR 0x1B
52#define TWL6040_REG_HKCTL1 0x1C
53#define TWL6040_REG_HKCTL2 0x1D
54#define TWL6040_REG_GPOCTL 0x1E
55#define TWL6040_REG_ALB 0x1F
56#define TWL6040_REG_DLB 0x20
57#define TWL6040_REG_TRIM1 0x28
58#define TWL6040_REG_TRIM2 0x29
59#define TWL6040_REG_TRIM3 0x2A
60#define TWL6040_REG_HSOTRIM 0x2B
61#define TWL6040_REG_HFOTRIM 0x2C
62#define TWL6040_REG_ACCCTL 0x2D
63#define TWL6040_REG_STATUS 0x2E
64
65#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
66
67#define TWL6040_VIOREGNUM 18
68#define TWL6040_VDDREGNUM 21
69
70/* INTID (0x03) fields */
71
72#define TWL6040_THINT 0x01
73#define TWL6040_PLUGINT 0x02
74#define TWL6040_UNPLUGINT 0x04
75#define TWL6040_HOOKINT 0x08
76#define TWL6040_HFINT 0x10
77#define TWL6040_VIBINT 0x20
78#define TWL6040_READYINT 0x40
79
80/* INTMR (0x04) fields */
81
82#define TWL6040_READYMSK 0x40
83#define TWL6040_ALLINT_MSK 0x7B
84
85/* NCPCTL (0x05) fields */
86
87#define TWL6040_NCPENA 0x01
88#define TWL6040_NCPOPEN 0x40
89
90/* LDOCTL (0x06) fields */
91
92#define TWL6040_LSLDOENA 0x01
93#define TWL6040_HSLDOENA 0x04
94#define TWL6040_REFENA 0x40
95#define TWL6040_OSCENA 0x80
96
97/* HPPLLCTL (0x07) fields */
98
99#define TWL6040_HPLLENA 0x01
100#define TWL6040_HPLLRST 0x02
101#define TWL6040_HPLLBP 0x04
102#define TWL6040_HPLLSQRENA 0x08
103#define TWL6040_HPLLSQRBP 0x10
104#define TWL6040_MCLK_12000KHZ (0 << 5)
105#define TWL6040_MCLK_19200KHZ (1 << 5)
106#define TWL6040_MCLK_26000KHZ (2 << 5)
107#define TWL6040_MCLK_38400KHZ (3 << 5)
108#define TWL6040_MCLK_MSK 0x60
109
110/* LPPLLCTL (0x08) fields */
111
112#define TWL6040_LPLLENA 0x01
113#define TWL6040_LPLLRST 0x02
114#define TWL6040_LPLLSEL 0x04
115#define TWL6040_LPLLFIN 0x08
116#define TWL6040_HPLLSEL 0x10
117
118/* HSLCTL (0x10) fields */
119
120#define TWL6040_HSDACMODEL 0x02
121#define TWL6040_HSDRVMODEL 0x08
122
123/* HSRCTL (0x11) fields */
124
125#define TWL6040_HSDACMODER 0x02
126#define TWL6040_HSDRVMODER 0x08
127
128/* ACCCTL (0x2D) fields */
129
130#define TWL6040_RESETSPLIT 0x04
131
132#define TWL6040_SYSCLK_SEL_LPPLL 1
133#define TWL6040_SYSCLK_SEL_HPPLL 2
134
135#define TWL6040_HPPLL_ID 1
136#define TWL6040_LPPLL_ID 2
137
138extern struct snd_soc_dai twl6040_dai;
139extern struct snd_soc_codec_device soc_codec_dev_twl6040;
140
141#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index df2c6d9617fb..8ac92f5e4f91 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -54,6 +54,7 @@ struct wm8350_output {
54struct wm8350_jack_data { 54struct wm8350_jack_data {
55 struct snd_soc_jack *jack; 55 struct snd_soc_jack *jack;
56 int report; 56 int report;
57 int short_report;
57}; 58};
58 59
59struct wm8350_data { 60struct wm8350_data {
@@ -62,6 +63,7 @@ struct wm8350_data {
62 struct wm8350_output out2; 63 struct wm8350_output out2;
63 struct wm8350_jack_data hpl; 64 struct wm8350_jack_data hpl;
64 struct wm8350_jack_data hpr; 65 struct wm8350_jack_data hpr;
66 struct wm8350_jack_data mic;
65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 67 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
66 int fll_freq_out; 68 int fll_freq_out;
67 int fll_freq_in; 69 int fll_freq_in;
@@ -1391,7 +1393,8 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
1391 * @jack: jack to report detection events on 1393 * @jack: jack to report detection events on
1392 * @report: value to report 1394 * @report: value to report
1393 * 1395 *
1394 * Enables the headphone jack detection of the WM8350. 1396 * Enables the headphone jack detection of the WM8350. If no report
1397 * is specified then detection is disabled.
1395 */ 1398 */
1396int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, 1399int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1397 struct snd_soc_jack *jack, int report) 1400 struct snd_soc_jack *jack, int report)
@@ -1420,8 +1423,12 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1420 return -EINVAL; 1423 return -EINVAL;
1421 } 1424 }
1422 1425
1423 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); 1426 if (report) {
1424 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); 1427 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1428 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
1429 } else {
1430 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, ena);
1431 }
1425 1432
1426 /* Sync status */ 1433 /* Sync status */
1427 wm8350_hp_jack_handler(irq + wm8350->irq_base, priv); 1434 wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
@@ -1430,6 +1437,60 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1430} 1437}
1431EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); 1438EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
1432 1439
1440static irqreturn_t wm8350_mic_handler(int irq, void *data)
1441{
1442 struct wm8350_data *priv = data;
1443 struct wm8350 *wm8350 = priv->codec.control_data;
1444 u16 reg;
1445 int report = 0;
1446
1447 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
1448 if (reg & WM8350_JACK_MICSCD_LVL)
1449 report |= priv->mic.short_report;
1450 if (reg & WM8350_JACK_MICSD_LVL)
1451 report |= priv->mic.report;
1452
1453 snd_soc_jack_report(priv->mic.jack, report,
1454 priv->mic.report | priv->mic.short_report);
1455
1456 return IRQ_HANDLED;
1457}
1458
1459/**
1460 * wm8350_mic_jack_detect - Enable microphone jack detection.
1461 *
1462 * @codec: WM8350 codec
1463 * @jack: jack to report detection events on
1464 * @detect_report: value to report when presence detected
1465 * @short_report: value to report when microphone short detected
1466 *
1467 * Enables the microphone jack detection of the WM8350. If both reports
1468 * are specified as zero then detection is disabled.
1469 */
1470int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
1471 struct snd_soc_jack *jack,
1472 int detect_report, int short_report)
1473{
1474 struct wm8350_data *priv = codec->private_data;
1475 struct wm8350 *wm8350 = codec->control_data;
1476
1477 priv->mic.jack = jack;
1478 priv->mic.report = detect_report;
1479 priv->mic.short_report = short_report;
1480
1481 if (detect_report || short_report) {
1482 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1483 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_1,
1484 WM8350_MIC_DET_ENA);
1485 } else {
1486 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_1,
1487 WM8350_MIC_DET_ENA);
1488 }
1489
1490 return 0;
1491}
1492EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
1493
1433static struct snd_soc_codec *wm8350_codec; 1494static struct snd_soc_codec *wm8350_codec;
1434 1495
1435static int wm8350_probe(struct platform_device *pdev) 1496static int wm8350_probe(struct platform_device *pdev)
@@ -1493,6 +1554,10 @@ static int wm8350_probe(struct platform_device *pdev)
1493 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, 1554 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
1494 wm8350_hp_jack_handler, 0, "Right jack detect", 1555 wm8350_hp_jack_handler, 0, "Right jack detect",
1495 priv); 1556 priv);
1557 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
1558 wm8350_mic_handler, 0, "Microphone short", priv);
1559 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
1560 wm8350_mic_handler, 0, "Microphone detect", priv);
1496 1561
1497 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1562 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1498 if (ret < 0) { 1563 if (ret < 0) {
@@ -1521,11 +1586,14 @@ static int wm8350_remove(struct platform_device *pdev)
1521 WM8350_JDL_ENA | WM8350_JDR_ENA); 1586 WM8350_JDL_ENA | WM8350_JDR_ENA);
1522 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); 1587 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1523 1588
1589 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICD, priv);
1590 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv);
1524 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); 1591 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
1525 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); 1592 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
1526 1593
1527 priv->hpl.jack = NULL; 1594 priv->hpl.jack = NULL;
1528 priv->hpr.jack = NULL; 1595 priv->hpr.jack = NULL;
1596 priv->mic.jack = NULL;
1529 1597
1530 /* cancel any work waiting to be queued. */ 1598 /* cancel any work waiting to be queued. */
1531 ret = cancel_delayed_work(&codec->delayed_work); 1599 ret = cancel_delayed_work(&codec->delayed_work);
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d088eb4b88bb..9ed0467c71db 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -25,5 +25,8 @@ enum wm8350_jack {
25 25
26int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, 26int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
27 struct snd_soc_jack *jack, int report); 27 struct snd_soc_jack *jack, int report);
28int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
29 struct snd_soc_jack *jack,
30 int detect_report, int short_report);
28 31
29#endif 32#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 475c67ac7818..ee084083a49d 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -29,8 +29,6 @@
29 29
30#include "wm8750.h" 30#include "wm8750.h"
31 31
32#define WM8750_VERSION "0.12"
33
34/* codec private data */ 32/* codec private data */
35struct wm8750_priv { 33struct wm8750_priv {
36 unsigned int sysclk; 34 unsigned int sysclk;
@@ -613,10 +611,16 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
613 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 611 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
614 break; 612 break;
615 case SND_SOC_BIAS_PREPARE: 613 case SND_SOC_BIAS_PREPARE:
616 /* set vmid to 5k for quick power up */
617 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
618 break; 614 break;
619 case SND_SOC_BIAS_STANDBY: 615 case SND_SOC_BIAS_STANDBY:
616 if (codec->bias_level == SND_SOC_BIAS_OFF) {
617 /* Set VMID to 5k */
618 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
619
620 /* ...and ramp */
621 msleep(1000);
622 }
623
620 /* mute dac and set vmid to 500k, enable VREF */ 624 /* mute dac and set vmid to 500k, enable VREF */
621 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 625 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
622 break; 626 break;
@@ -660,13 +664,6 @@ struct snd_soc_dai wm8750_dai = {
660}; 664};
661EXPORT_SYMBOL_GPL(wm8750_dai); 665EXPORT_SYMBOL_GPL(wm8750_dai);
662 666
663static void wm8750_work(struct work_struct *work)
664{
665 struct snd_soc_codec *codec =
666 container_of(work, struct snd_soc_codec, delayed_work.work);
667 wm8750_set_bias_level(codec, codec->bias_level);
668}
669
670static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) 667static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
671{ 668{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 669 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -695,14 +692,6 @@ static int wm8750_resume(struct platform_device *pdev)
695 692
696 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 693 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
697 694
698 /* charge wm8750 caps */
699 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
700 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
701 codec->bias_level = SND_SOC_BIAS_ON;
702 schedule_delayed_work(&codec->delayed_work,
703 msecs_to_jiffies(1000));
704 }
705
706 return 0; 695 return 0;
707} 696}
708 697
@@ -746,9 +735,7 @@ static int wm8750_init(struct snd_soc_device *socdev,
746 } 735 }
747 736
748 /* charge output caps */ 737 /* charge output caps */
749 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 738 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
750 codec->bias_level = SND_SOC_BIAS_STANDBY;
751 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
752 739
753 /* set the update bits */ 740 /* set the update bits */
754 reg = snd_soc_read(codec, WM8750_LDAC); 741 reg = snd_soc_read(codec, WM8750_LDAC);
@@ -912,7 +899,6 @@ static int wm8750_probe(struct platform_device *pdev)
912 struct wm8750_priv *wm8750; 899 struct wm8750_priv *wm8750;
913 int ret; 900 int ret;
914 901
915 pr_info("WM8750 Audio Codec %s", WM8750_VERSION);
916 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 902 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
917 if (codec == NULL) 903 if (codec == NULL)
918 return -ENOMEM; 904 return -ENOMEM;
@@ -929,7 +915,6 @@ static int wm8750_probe(struct platform_device *pdev)
929 INIT_LIST_HEAD(&codec->dapm_widgets); 915 INIT_LIST_HEAD(&codec->dapm_widgets);
930 INIT_LIST_HEAD(&codec->dapm_paths); 916 INIT_LIST_HEAD(&codec->dapm_paths);
931 wm8750_socdev = socdev; 917 wm8750_socdev = socdev;
932 INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
933 918
934 ret = -ENODEV; 919 ret = -ENODEV;
935 920
@@ -953,25 +938,6 @@ static int wm8750_probe(struct platform_device *pdev)
953 return ret; 938 return ret;
954} 939}
955 940
956/*
957 * This function forces any delayed work to be queued and run.
958 */
959static int run_delayed_work(struct delayed_work *dwork)
960{
961 int ret;
962
963 /* cancel any work waiting to be queued. */
964 ret = cancel_delayed_work(dwork);
965
966 /* if there was any work waiting then we run it now and
967 * wait for it's completion */
968 if (ret) {
969 schedule_delayed_work(dwork, 0);
970 flush_scheduled_work();
971 }
972 return ret;
973}
974
975/* power down chip */ 941/* power down chip */
976static int wm8750_remove(struct platform_device *pdev) 942static int wm8750_remove(struct platform_device *pdev)
977{ 943{
@@ -980,7 +946,6 @@ static int wm8750_remove(struct platform_device *pdev)
980 946
981 if (codec->control_data) 947 if (codec->control_data)
982 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); 948 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
983 run_delayed_work(&codec->delayed_work);
984 snd_soc_free_pcms(socdev); 949 snd_soc_free_pcms(socdev);
985 snd_soc_dapm_free(socdev); 950 snd_soc_dapm_free(socdev);
986#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 951#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 3595bd57c4eb..134b17532f23 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -11,25 +11,26 @@
11 * 11 *
12 * TODO: 12 * TODO:
13 * - TDM mode configuration. 13 * - TDM mode configuration.
14 * - Mic detect.
15 * - Digital microphone support. 14 * - Digital microphone support.
16 * - Interrupt support (mic detect and sequencer).
17 */ 15 */
18 16
19#include <linux/module.h> 17#include <linux/module.h>
20#include <linux/moduleparam.h> 18#include <linux/moduleparam.h>
21#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/completion.h>
22#include <linux/delay.h> 21#include <linux/delay.h>
23#include <linux/pm.h> 22#include <linux/pm.h>
24#include <linux/i2c.h> 23#include <linux/i2c.h>
25#include <linux/platform_device.h> 24#include <linux/platform_device.h>
26#include <sound/core.h> 25#include <sound/core.h>
26#include <sound/jack.h>
27#include <sound/pcm.h> 27#include <sound/pcm.h>
28#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
29#include <sound/tlv.h> 29#include <sound/tlv.h>
30#include <sound/soc.h> 30#include <sound/soc.h>
31#include <sound/soc-dapm.h> 31#include <sound/soc-dapm.h>
32#include <sound/initval.h> 32#include <sound/initval.h>
33#include <sound/wm8903.h>
33 34
34#include "wm8903.h" 35#include "wm8903.h"
35 36
@@ -221,6 +222,14 @@ struct wm8903_priv {
221 int playback_active; 222 int playback_active;
222 int capture_active; 223 int capture_active;
223 224
225 struct completion wseq;
226
227 struct snd_soc_jack *mic_jack;
228 int mic_det;
229 int mic_short;
230 int mic_last_report;
231 int mic_delay;
232
224 struct snd_pcm_substream *master_substream; 233 struct snd_pcm_substream *master_substream;
225 struct snd_pcm_substream *slave_substream; 234 struct snd_pcm_substream *slave_substream;
226}; 235};
@@ -243,13 +252,14 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
243{ 252{
244 u16 reg[5]; 253 u16 reg[5];
245 struct i2c_client *i2c = codec->control_data; 254 struct i2c_client *i2c = codec->control_data;
255 struct wm8903_priv *wm8903 = codec->private_data;
246 256
247 BUG_ON(start > 48); 257 BUG_ON(start > 48);
248 258
249 /* Enable the sequencer */ 259 /* Enable the sequencer if it's not already on */
250 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); 260 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
251 reg[0] |= WM8903_WSEQ_ENA; 261 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
252 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); 262 reg[0] | WM8903_WSEQ_ENA);
253 263
254 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); 264 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
255 265
@@ -257,20 +267,19 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
257 start | WM8903_WSEQ_START); 267 start | WM8903_WSEQ_START);
258 268
259 /* Wait for it to complete. If we have the interrupt wired up then 269 /* Wait for it to complete. If we have the interrupt wired up then
260 * we could block waiting for an interrupt, though polling may still 270 * that will break us out of the poll early.
261 * be desirable for diagnostic purposes.
262 */ 271 */
263 do { 272 do {
264 msleep(10); 273 wait_for_completion_timeout(&wm8903->wseq,
274 msecs_to_jiffies(10));
265 275
266 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); 276 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
267 } while (reg[4] & WM8903_WSEQ_BUSY); 277 } while (reg[4] & WM8903_WSEQ_BUSY);
268 278
269 dev_dbg(&i2c->dev, "Sequence complete\n"); 279 dev_dbg(&i2c->dev, "Sequence complete\n");
270 280
271 /* Disable the sequencer again */ 281 /* Disable the sequencer again if we enabled it */
272 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 282 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
273 reg[0] & ~WM8903_WSEQ_ENA);
274 283
275 return 0; 284 return 0;
276} 285}
@@ -1435,6 +1444,116 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1435 return 0; 1444 return 0;
1436} 1445}
1437 1446
1447/**
1448 * wm8903_mic_detect - Enable microphone detection via the WM8903 IRQ
1449 *
1450 * @codec: WM8903 codec
1451 * @jack: jack to report detection events on
1452 * @det: value to report for presence detection
1453 * @shrt: value to report for short detection
1454 *
1455 * Enable microphone detection via IRQ on the WM8903. If GPIOs are
1456 * being used to bring out signals to the processor then only platform
1457 * data configuration is needed for WM8903 and processor GPIOs should
1458 * be configured using snd_soc_jack_add_gpios() instead.
1459 *
1460 * The current threasholds for detection should be configured using
1461 * micdet_cfg in the platform data. Using this function will force on
1462 * the microphone bias for the device.
1463 */
1464int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
1465 int det, int shrt)
1466{
1467 struct wm8903_priv *wm8903 = codec->private_data;
1468 int irq_mask = WM8903_MICDET_EINT | WM8903_MICSHRT_EINT;
1469
1470 dev_dbg(codec->dev, "Enabling microphone detection: %x %x\n",
1471 det, shrt);
1472
1473 /* Store the configuration */
1474 wm8903->mic_jack = jack;
1475 wm8903->mic_det = det;
1476 wm8903->mic_short = shrt;
1477
1478 /* Enable interrupts we've got a report configured for */
1479 if (det)
1480 irq_mask &= ~WM8903_MICDET_EINT;
1481 if (shrt)
1482 irq_mask &= ~WM8903_MICSHRT_EINT;
1483
1484 snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
1485 WM8903_MICDET_EINT | WM8903_MICSHRT_EINT,
1486 irq_mask);
1487
1488 if (det && shrt) {
1489 /* Enable mic detection, this may not have been set through
1490 * platform data (eg, if the defaults are OK). */
1491 snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
1492 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
1493 snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0,
1494 WM8903_MICDET_ENA, WM8903_MICDET_ENA);
1495 } else {
1496 snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0,
1497 WM8903_MICDET_ENA, 0);
1498 }
1499
1500 return 0;
1501}
1502EXPORT_SYMBOL_GPL(wm8903_mic_detect);
1503
1504static irqreturn_t wm8903_irq(int irq, void *data)
1505{
1506 struct wm8903_priv *wm8903 = data;
1507 struct snd_soc_codec *codec = &wm8903->codec;
1508 int mic_report;
1509 int int_pol;
1510 int int_val = 0;
1511 int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK);
1512
1513 int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask;
1514
1515 if (int_val & WM8903_WSEQ_BUSY_EINT) {
1516 dev_dbg(codec->dev, "Write sequencer done\n");
1517 complete(&wm8903->wseq);
1518 }
1519
1520 /*
1521 * The rest is microphone jack detection. We need to manually
1522 * invert the polarity of the interrupt after each event - to
1523 * simplify the code keep track of the last state we reported
1524 * and just invert the relevant bits in both the report and
1525 * the polarity register.
1526 */
1527 mic_report = wm8903->mic_last_report;
1528 int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1);
1529
1530 if (int_val & WM8903_MICSHRT_EINT) {
1531 dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol);
1532
1533 mic_report ^= wm8903->mic_short;
1534 int_pol ^= WM8903_MICSHRT_INV;
1535 }
1536
1537 if (int_val & WM8903_MICDET_EINT) {
1538 dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol);
1539
1540 mic_report ^= wm8903->mic_det;
1541 int_pol ^= WM8903_MICDET_INV;
1542
1543 msleep(wm8903->mic_delay);
1544 }
1545
1546 snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1,
1547 WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol);
1548
1549 snd_soc_jack_report(wm8903->mic_jack, mic_report,
1550 wm8903->mic_short | wm8903->mic_det);
1551
1552 wm8903->mic_last_report = mic_report;
1553
1554 return IRQ_HANDLED;
1555}
1556
1438#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ 1557#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
1439 SNDRV_PCM_RATE_11025 | \ 1558 SNDRV_PCM_RATE_11025 | \
1440 SNDRV_PCM_RATE_16000 | \ 1559 SNDRV_PCM_RATE_16000 | \
@@ -1529,9 +1648,11 @@ static struct snd_soc_codec *wm8903_codec;
1529static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, 1648static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1530 const struct i2c_device_id *id) 1649 const struct i2c_device_id *id)
1531{ 1650{
1651 struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
1532 struct wm8903_priv *wm8903; 1652 struct wm8903_priv *wm8903;
1533 struct snd_soc_codec *codec; 1653 struct snd_soc_codec *codec;
1534 int ret; 1654 int ret, i;
1655 int trigger, irq_pol;
1535 u16 val; 1656 u16 val;
1536 1657
1537 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); 1658 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
@@ -1555,6 +1676,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1555 codec->reg_cache = &wm8903->reg_cache[0]; 1676 codec->reg_cache = &wm8903->reg_cache[0];
1556 codec->private_data = wm8903; 1677 codec->private_data = wm8903;
1557 codec->volatile_register = wm8903_volatile_register; 1678 codec->volatile_register = wm8903_volatile_register;
1679 init_completion(&wm8903->wseq);
1558 1680
1559 i2c_set_clientdata(i2c, codec); 1681 i2c_set_clientdata(i2c, codec);
1560 codec->control_data = i2c; 1682 codec->control_data = i2c;
@@ -1578,6 +1700,53 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1578 1700
1579 wm8903_reset(codec); 1701 wm8903_reset(codec);
1580 1702
1703 /* Set up GPIOs and microphone detection */
1704 if (pdata) {
1705 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
1706 if (!pdata->gpio_cfg[i])
1707 continue;
1708
1709 snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
1710 pdata->gpio_cfg[i] & 0xffff);
1711 }
1712
1713 snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
1714 pdata->micdet_cfg);
1715
1716 /* Microphone detection needs the WSEQ clock */
1717 if (pdata->micdet_cfg)
1718 snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
1719 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
1720
1721 wm8903->mic_delay = pdata->micdet_delay;
1722 }
1723
1724 if (i2c->irq) {
1725 if (pdata && pdata->irq_active_low) {
1726 trigger = IRQF_TRIGGER_LOW;
1727 irq_pol = WM8903_IRQ_POL;
1728 } else {
1729 trigger = IRQF_TRIGGER_HIGH;
1730 irq_pol = 0;
1731 }
1732
1733 snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
1734 WM8903_IRQ_POL, irq_pol);
1735
1736 ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
1737 trigger | IRQF_ONESHOT,
1738 "wm8903", wm8903);
1739 if (ret != 0) {
1740 dev_err(&i2c->dev, "Failed to request IRQ: %d\n",
1741 ret);
1742 goto err;
1743 }
1744
1745 /* Enable write sequencer interrupts */
1746 snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
1747 WM8903_IM_WSEQ_BUSY_EINT, 0);
1748 }
1749
1581 /* power on device */ 1750 /* power on device */
1582 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1751 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1583 1752
@@ -1618,7 +1787,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1618 ret = snd_soc_register_codec(codec); 1787 ret = snd_soc_register_codec(codec);
1619 if (ret != 0) { 1788 if (ret != 0) {
1620 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 1789 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1621 goto err; 1790 goto err_irq;
1622 } 1791 }
1623 1792
1624 ret = snd_soc_register_dai(&wm8903_dai); 1793 ret = snd_soc_register_dai(&wm8903_dai);
@@ -1631,6 +1800,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1631 1800
1632err_codec: 1801err_codec:
1633 snd_soc_unregister_codec(codec); 1802 snd_soc_unregister_codec(codec);
1803err_irq:
1804 if (i2c->irq)
1805 free_irq(i2c->irq, wm8903);
1634err: 1806err:
1635 wm8903_codec = NULL; 1807 wm8903_codec = NULL;
1636 kfree(wm8903); 1808 kfree(wm8903);
@@ -1640,12 +1812,16 @@ err:
1640static __devexit int wm8903_i2c_remove(struct i2c_client *client) 1812static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1641{ 1813{
1642 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1814 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1815 struct wm8903_priv *priv = codec->private_data;
1643 1816
1644 snd_soc_unregister_dai(&wm8903_dai); 1817 snd_soc_unregister_dai(&wm8903_dai);
1645 snd_soc_unregister_codec(codec); 1818 snd_soc_unregister_codec(codec);
1646 1819
1647 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1820 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1648 1821
1822 if (client->irq)
1823 free_irq(client->irq, priv);
1824
1649 kfree(codec->private_data); 1825 kfree(codec->private_data);
1650 1826
1651 wm8903_codec = NULL; 1827 wm8903_codec = NULL;
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index 0ea27e2b9963..ce384a2ad820 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -18,6 +18,10 @@
18extern struct snd_soc_dai wm8903_dai; 18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903; 19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20 20
21extern int wm8903_mic_detect(struct snd_soc_codec *codec,
22 struct snd_soc_jack *jack,
23 int det, int shrt);
24
21#define WM8903_MCLK_DIV_2 1 25#define WM8903_MCLK_DIV_2 1
22#define WM8903_CLK_SYS 2 26#define WM8903_CLK_SYS 2
23#define WM8903_BCLK 3 27#define WM8903_BCLK 3
@@ -173,28 +177,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8903;
173#define WM8903_VMID_RES_5K 4 177#define WM8903_VMID_RES_5K 4
174 178
175/* 179/*
176 * R6 (0x06) - Mic Bias Control 0
177 */
178#define WM8903_MICDET_HYST_ENA 0x0080 /* MICDET_HYST_ENA */
179#define WM8903_MICDET_HYST_ENA_MASK 0x0080 /* MICDET_HYST_ENA */
180#define WM8903_MICDET_HYST_ENA_SHIFT 7 /* MICDET_HYST_ENA */
181#define WM8903_MICDET_HYST_ENA_WIDTH 1 /* MICDET_HYST_ENA */
182#define WM8903_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
183#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
184#define WM8903_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
185#define WM8903_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
186#define WM8903_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
187#define WM8903_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
188#define WM8903_MICDET_ENA 0x0002 /* MICDET_ENA */
189#define WM8903_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
190#define WM8903_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
191#define WM8903_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
192#define WM8903_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
193#define WM8903_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
194#define WM8903_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
195#define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
196
197/*
198 * R8 (0x08) - Analogue DAC 0 180 * R8 (0x08) - Analogue DAC 0
199 */ 181 */
200#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */ 182#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */
@@ -1135,201 +1117,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8903;
1135#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ 1117#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */
1136 1118
1137/* 1119/*
1138 * R116 (0x74) - GPIO Control 1
1139 */
1140#define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */
1141#define WM8903_GP1_FN_SHIFT 8 /* GP1_FN - [12:8] */
1142#define WM8903_GP1_FN_WIDTH 5 /* GP1_FN - [12:8] */
1143#define WM8903_GP1_DIR 0x0080 /* GP1_DIR */
1144#define WM8903_GP1_DIR_MASK 0x0080 /* GP1_DIR */
1145#define WM8903_GP1_DIR_SHIFT 7 /* GP1_DIR */
1146#define WM8903_GP1_DIR_WIDTH 1 /* GP1_DIR */
1147#define WM8903_GP1_OP_CFG 0x0040 /* GP1_OP_CFG */
1148#define WM8903_GP1_OP_CFG_MASK 0x0040 /* GP1_OP_CFG */
1149#define WM8903_GP1_OP_CFG_SHIFT 6 /* GP1_OP_CFG */
1150#define WM8903_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
1151#define WM8903_GP1_IP_CFG 0x0020 /* GP1_IP_CFG */
1152#define WM8903_GP1_IP_CFG_MASK 0x0020 /* GP1_IP_CFG */
1153#define WM8903_GP1_IP_CFG_SHIFT 5 /* GP1_IP_CFG */
1154#define WM8903_GP1_IP_CFG_WIDTH 1 /* GP1_IP_CFG */
1155#define WM8903_GP1_LVL 0x0010 /* GP1_LVL */
1156#define WM8903_GP1_LVL_MASK 0x0010 /* GP1_LVL */
1157#define WM8903_GP1_LVL_SHIFT 4 /* GP1_LVL */
1158#define WM8903_GP1_LVL_WIDTH 1 /* GP1_LVL */
1159#define WM8903_GP1_PD 0x0008 /* GP1_PD */
1160#define WM8903_GP1_PD_MASK 0x0008 /* GP1_PD */
1161#define WM8903_GP1_PD_SHIFT 3 /* GP1_PD */
1162#define WM8903_GP1_PD_WIDTH 1 /* GP1_PD */
1163#define WM8903_GP1_PU 0x0004 /* GP1_PU */
1164#define WM8903_GP1_PU_MASK 0x0004 /* GP1_PU */
1165#define WM8903_GP1_PU_SHIFT 2 /* GP1_PU */
1166#define WM8903_GP1_PU_WIDTH 1 /* GP1_PU */
1167#define WM8903_GP1_INTMODE 0x0002 /* GP1_INTMODE */
1168#define WM8903_GP1_INTMODE_MASK 0x0002 /* GP1_INTMODE */
1169#define WM8903_GP1_INTMODE_SHIFT 1 /* GP1_INTMODE */
1170#define WM8903_GP1_INTMODE_WIDTH 1 /* GP1_INTMODE */
1171#define WM8903_GP1_DB 0x0001 /* GP1_DB */
1172#define WM8903_GP1_DB_MASK 0x0001 /* GP1_DB */
1173#define WM8903_GP1_DB_SHIFT 0 /* GP1_DB */
1174#define WM8903_GP1_DB_WIDTH 1 /* GP1_DB */
1175
1176/*
1177 * R117 (0x75) - GPIO Control 2
1178 */
1179#define WM8903_GP2_FN_MASK 0x1F00 /* GP2_FN - [12:8] */
1180#define WM8903_GP2_FN_SHIFT 8 /* GP2_FN - [12:8] */
1181#define WM8903_GP2_FN_WIDTH 5 /* GP2_FN - [12:8] */
1182#define WM8903_GP2_DIR 0x0080 /* GP2_DIR */
1183#define WM8903_GP2_DIR_MASK 0x0080 /* GP2_DIR */
1184#define WM8903_GP2_DIR_SHIFT 7 /* GP2_DIR */
1185#define WM8903_GP2_DIR_WIDTH 1 /* GP2_DIR */
1186#define WM8903_GP2_OP_CFG 0x0040 /* GP2_OP_CFG */
1187#define WM8903_GP2_OP_CFG_MASK 0x0040 /* GP2_OP_CFG */
1188#define WM8903_GP2_OP_CFG_SHIFT 6 /* GP2_OP_CFG */
1189#define WM8903_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
1190#define WM8903_GP2_IP_CFG 0x0020 /* GP2_IP_CFG */
1191#define WM8903_GP2_IP_CFG_MASK 0x0020 /* GP2_IP_CFG */
1192#define WM8903_GP2_IP_CFG_SHIFT 5 /* GP2_IP_CFG */
1193#define WM8903_GP2_IP_CFG_WIDTH 1 /* GP2_IP_CFG */
1194#define WM8903_GP2_LVL 0x0010 /* GP2_LVL */
1195#define WM8903_GP2_LVL_MASK 0x0010 /* GP2_LVL */
1196#define WM8903_GP2_LVL_SHIFT 4 /* GP2_LVL */
1197#define WM8903_GP2_LVL_WIDTH 1 /* GP2_LVL */
1198#define WM8903_GP2_PD 0x0008 /* GP2_PD */
1199#define WM8903_GP2_PD_MASK 0x0008 /* GP2_PD */
1200#define WM8903_GP2_PD_SHIFT 3 /* GP2_PD */
1201#define WM8903_GP2_PD_WIDTH 1 /* GP2_PD */
1202#define WM8903_GP2_PU 0x0004 /* GP2_PU */
1203#define WM8903_GP2_PU_MASK 0x0004 /* GP2_PU */
1204#define WM8903_GP2_PU_SHIFT 2 /* GP2_PU */
1205#define WM8903_GP2_PU_WIDTH 1 /* GP2_PU */
1206#define WM8903_GP2_INTMODE 0x0002 /* GP2_INTMODE */
1207#define WM8903_GP2_INTMODE_MASK 0x0002 /* GP2_INTMODE */
1208#define WM8903_GP2_INTMODE_SHIFT 1 /* GP2_INTMODE */
1209#define WM8903_GP2_INTMODE_WIDTH 1 /* GP2_INTMODE */
1210#define WM8903_GP2_DB 0x0001 /* GP2_DB */
1211#define WM8903_GP2_DB_MASK 0x0001 /* GP2_DB */
1212#define WM8903_GP2_DB_SHIFT 0 /* GP2_DB */
1213#define WM8903_GP2_DB_WIDTH 1 /* GP2_DB */
1214
1215/*
1216 * R118 (0x76) - GPIO Control 3
1217 */
1218#define WM8903_GP3_FN_MASK 0x1F00 /* GP3_FN - [12:8] */
1219#define WM8903_GP3_FN_SHIFT 8 /* GP3_FN - [12:8] */
1220#define WM8903_GP3_FN_WIDTH 5 /* GP3_FN - [12:8] */
1221#define WM8903_GP3_DIR 0x0080 /* GP3_DIR */
1222#define WM8903_GP3_DIR_MASK 0x0080 /* GP3_DIR */
1223#define WM8903_GP3_DIR_SHIFT 7 /* GP3_DIR */
1224#define WM8903_GP3_DIR_WIDTH 1 /* GP3_DIR */
1225#define WM8903_GP3_OP_CFG 0x0040 /* GP3_OP_CFG */
1226#define WM8903_GP3_OP_CFG_MASK 0x0040 /* GP3_OP_CFG */
1227#define WM8903_GP3_OP_CFG_SHIFT 6 /* GP3_OP_CFG */
1228#define WM8903_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
1229#define WM8903_GP3_IP_CFG 0x0020 /* GP3_IP_CFG */
1230#define WM8903_GP3_IP_CFG_MASK 0x0020 /* GP3_IP_CFG */
1231#define WM8903_GP3_IP_CFG_SHIFT 5 /* GP3_IP_CFG */
1232#define WM8903_GP3_IP_CFG_WIDTH 1 /* GP3_IP_CFG */
1233#define WM8903_GP3_LVL 0x0010 /* GP3_LVL */
1234#define WM8903_GP3_LVL_MASK 0x0010 /* GP3_LVL */
1235#define WM8903_GP3_LVL_SHIFT 4 /* GP3_LVL */
1236#define WM8903_GP3_LVL_WIDTH 1 /* GP3_LVL */
1237#define WM8903_GP3_PD 0x0008 /* GP3_PD */
1238#define WM8903_GP3_PD_MASK 0x0008 /* GP3_PD */
1239#define WM8903_GP3_PD_SHIFT 3 /* GP3_PD */
1240#define WM8903_GP3_PD_WIDTH 1 /* GP3_PD */
1241#define WM8903_GP3_PU 0x0004 /* GP3_PU */
1242#define WM8903_GP3_PU_MASK 0x0004 /* GP3_PU */
1243#define WM8903_GP3_PU_SHIFT 2 /* GP3_PU */
1244#define WM8903_GP3_PU_WIDTH 1 /* GP3_PU */
1245#define WM8903_GP3_INTMODE 0x0002 /* GP3_INTMODE */
1246#define WM8903_GP3_INTMODE_MASK 0x0002 /* GP3_INTMODE */
1247#define WM8903_GP3_INTMODE_SHIFT 1 /* GP3_INTMODE */
1248#define WM8903_GP3_INTMODE_WIDTH 1 /* GP3_INTMODE */
1249#define WM8903_GP3_DB 0x0001 /* GP3_DB */
1250#define WM8903_GP3_DB_MASK 0x0001 /* GP3_DB */
1251#define WM8903_GP3_DB_SHIFT 0 /* GP3_DB */
1252#define WM8903_GP3_DB_WIDTH 1 /* GP3_DB */
1253
1254/*
1255 * R119 (0x77) - GPIO Control 4
1256 */
1257#define WM8903_GP4_FN_MASK 0x1F00 /* GP4_FN - [12:8] */
1258#define WM8903_GP4_FN_SHIFT 8 /* GP4_FN - [12:8] */
1259#define WM8903_GP4_FN_WIDTH 5 /* GP4_FN - [12:8] */
1260#define WM8903_GP4_DIR 0x0080 /* GP4_DIR */
1261#define WM8903_GP4_DIR_MASK 0x0080 /* GP4_DIR */
1262#define WM8903_GP4_DIR_SHIFT 7 /* GP4_DIR */
1263#define WM8903_GP4_DIR_WIDTH 1 /* GP4_DIR */
1264#define WM8903_GP4_OP_CFG 0x0040 /* GP4_OP_CFG */
1265#define WM8903_GP4_OP_CFG_MASK 0x0040 /* GP4_OP_CFG */
1266#define WM8903_GP4_OP_CFG_SHIFT 6 /* GP4_OP_CFG */
1267#define WM8903_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
1268#define WM8903_GP4_IP_CFG 0x0020 /* GP4_IP_CFG */
1269#define WM8903_GP4_IP_CFG_MASK 0x0020 /* GP4_IP_CFG */
1270#define WM8903_GP4_IP_CFG_SHIFT 5 /* GP4_IP_CFG */
1271#define WM8903_GP4_IP_CFG_WIDTH 1 /* GP4_IP_CFG */
1272#define WM8903_GP4_LVL 0x0010 /* GP4_LVL */
1273#define WM8903_GP4_LVL_MASK 0x0010 /* GP4_LVL */
1274#define WM8903_GP4_LVL_SHIFT 4 /* GP4_LVL */
1275#define WM8903_GP4_LVL_WIDTH 1 /* GP4_LVL */
1276#define WM8903_GP4_PD 0x0008 /* GP4_PD */
1277#define WM8903_GP4_PD_MASK 0x0008 /* GP4_PD */
1278#define WM8903_GP4_PD_SHIFT 3 /* GP4_PD */
1279#define WM8903_GP4_PD_WIDTH 1 /* GP4_PD */
1280#define WM8903_GP4_PU 0x0004 /* GP4_PU */
1281#define WM8903_GP4_PU_MASK 0x0004 /* GP4_PU */
1282#define WM8903_GP4_PU_SHIFT 2 /* GP4_PU */
1283#define WM8903_GP4_PU_WIDTH 1 /* GP4_PU */
1284#define WM8903_GP4_INTMODE 0x0002 /* GP4_INTMODE */
1285#define WM8903_GP4_INTMODE_MASK 0x0002 /* GP4_INTMODE */
1286#define WM8903_GP4_INTMODE_SHIFT 1 /* GP4_INTMODE */
1287#define WM8903_GP4_INTMODE_WIDTH 1 /* GP4_INTMODE */
1288#define WM8903_GP4_DB 0x0001 /* GP4_DB */
1289#define WM8903_GP4_DB_MASK 0x0001 /* GP4_DB */
1290#define WM8903_GP4_DB_SHIFT 0 /* GP4_DB */
1291#define WM8903_GP4_DB_WIDTH 1 /* GP4_DB */
1292
1293/*
1294 * R120 (0x78) - GPIO Control 5
1295 */
1296#define WM8903_GP5_FN_MASK 0x1F00 /* GP5_FN - [12:8] */
1297#define WM8903_GP5_FN_SHIFT 8 /* GP5_FN - [12:8] */
1298#define WM8903_GP5_FN_WIDTH 5 /* GP5_FN - [12:8] */
1299#define WM8903_GP5_DIR 0x0080 /* GP5_DIR */
1300#define WM8903_GP5_DIR_MASK 0x0080 /* GP5_DIR */
1301#define WM8903_GP5_DIR_SHIFT 7 /* GP5_DIR */
1302#define WM8903_GP5_DIR_WIDTH 1 /* GP5_DIR */
1303#define WM8903_GP5_OP_CFG 0x0040 /* GP5_OP_CFG */
1304#define WM8903_GP5_OP_CFG_MASK 0x0040 /* GP5_OP_CFG */
1305#define WM8903_GP5_OP_CFG_SHIFT 6 /* GP5_OP_CFG */
1306#define WM8903_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
1307#define WM8903_GP5_IP_CFG 0x0020 /* GP5_IP_CFG */
1308#define WM8903_GP5_IP_CFG_MASK 0x0020 /* GP5_IP_CFG */
1309#define WM8903_GP5_IP_CFG_SHIFT 5 /* GP5_IP_CFG */
1310#define WM8903_GP5_IP_CFG_WIDTH 1 /* GP5_IP_CFG */
1311#define WM8903_GP5_LVL 0x0010 /* GP5_LVL */
1312#define WM8903_GP5_LVL_MASK 0x0010 /* GP5_LVL */
1313#define WM8903_GP5_LVL_SHIFT 4 /* GP5_LVL */
1314#define WM8903_GP5_LVL_WIDTH 1 /* GP5_LVL */
1315#define WM8903_GP5_PD 0x0008 /* GP5_PD */
1316#define WM8903_GP5_PD_MASK 0x0008 /* GP5_PD */
1317#define WM8903_GP5_PD_SHIFT 3 /* GP5_PD */
1318#define WM8903_GP5_PD_WIDTH 1 /* GP5_PD */
1319#define WM8903_GP5_PU 0x0004 /* GP5_PU */
1320#define WM8903_GP5_PU_MASK 0x0004 /* GP5_PU */
1321#define WM8903_GP5_PU_SHIFT 2 /* GP5_PU */
1322#define WM8903_GP5_PU_WIDTH 1 /* GP5_PU */
1323#define WM8903_GP5_INTMODE 0x0002 /* GP5_INTMODE */
1324#define WM8903_GP5_INTMODE_MASK 0x0002 /* GP5_INTMODE */
1325#define WM8903_GP5_INTMODE_SHIFT 1 /* GP5_INTMODE */
1326#define WM8903_GP5_INTMODE_WIDTH 1 /* GP5_INTMODE */
1327#define WM8903_GP5_DB 0x0001 /* GP5_DB */
1328#define WM8903_GP5_DB_MASK 0x0001 /* GP5_DB */
1329#define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */
1330#define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */
1331
1332/*
1333 * R121 (0x79) - Interrupt Status 1 1120 * R121 (0x79) - Interrupt Status 1
1334 */ 1121 */
1335#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */ 1122#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 593e47d0e0eb..c5b50d73f2d5 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2425,6 +2425,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
2425static int wm8904_register(struct wm8904_priv *wm8904, 2425static int wm8904_register(struct wm8904_priv *wm8904,
2426 enum snd_soc_control_type control) 2426 enum snd_soc_control_type control)
2427{ 2427{
2428 struct wm8904_pdata *pdata = wm8904->pdata;
2428 int ret; 2429 int ret;
2429 struct snd_soc_codec *codec = &wm8904->codec; 2430 struct snd_soc_codec *codec = &wm8904->codec;
2430 int i; 2431 int i;
@@ -2530,6 +2531,22 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2530 WM8904_LINEOUTRZC; 2531 WM8904_LINEOUTRZC;
2531 wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; 2532 wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
2532 2533
2534 /* Apply configuration from the platform data. */
2535 if (wm8904->pdata) {
2536 for (i = 0; i < WM8904_GPIO_REGS; i++) {
2537 if (!pdata->gpio_cfg[i])
2538 continue;
2539
2540 wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i]
2541 = pdata->gpio_cfg[i] & 0xffff;
2542 }
2543
2544 /* Zero is the default value for these anyway */
2545 for (i = 0; i < WM8904_MIC_REGS; i++)
2546 wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
2547 = pdata->mic_cfg[i];
2548 }
2549
2533 /* Set Class W by default - this will be managed by the Class 2550 /* Set Class W by default - this will be managed by the Class
2534 * G widget at runtime where bypass paths are available. 2551 * G widget at runtime where bypass paths are available.
2535 */ 2552 */
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index b68886df34e4..abe5059b3004 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -186,39 +186,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8904;
186#define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */ 186#define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */
187 187
188/* 188/*
189 * R6 (0x06) - Mic Bias Control 0
190 */
191#define WM8904_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
192#define WM8904_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
193#define WM8904_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
194#define WM8904_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
195#define WM8904_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
196#define WM8904_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
197#define WM8904_MICDET_ENA 0x0002 /* MICDET_ENA */
198#define WM8904_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
199#define WM8904_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
200#define WM8904_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
201#define WM8904_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
202#define WM8904_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
203#define WM8904_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
204#define WM8904_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
205
206/*
207 * R7 (0x07) - Mic Bias Control 1
208 */
209#define WM8904_MIC_DET_FILTER_ENA 0x8000 /* MIC_DET_FILTER_ENA */
210#define WM8904_MIC_DET_FILTER_ENA_MASK 0x8000 /* MIC_DET_FILTER_ENA */
211#define WM8904_MIC_DET_FILTER_ENA_SHIFT 15 /* MIC_DET_FILTER_ENA */
212#define WM8904_MIC_DET_FILTER_ENA_WIDTH 1 /* MIC_DET_FILTER_ENA */
213#define WM8904_MIC_SHORT_FILTER_ENA 0x4000 /* MIC_SHORT_FILTER_ENA */
214#define WM8904_MIC_SHORT_FILTER_ENA_MASK 0x4000 /* MIC_SHORT_FILTER_ENA */
215#define WM8904_MIC_SHORT_FILTER_ENA_SHIFT 14 /* MIC_SHORT_FILTER_ENA */
216#define WM8904_MIC_SHORT_FILTER_ENA_WIDTH 1 /* MIC_SHORT_FILTER_ENA */
217#define WM8904_MICBIAS_SEL_MASK 0x0007 /* MICBIAS_SEL - [2:0] */
218#define WM8904_MICBIAS_SEL_SHIFT 0 /* MICBIAS_SEL - [2:0] */
219#define WM8904_MICBIAS_SEL_WIDTH 3 /* MICBIAS_SEL - [2:0] */
220
221/*
222 * R8 (0x08) - Analogue DAC 0 189 * R8 (0x08) - Analogue DAC 0
223 */ 190 */
224#define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */ 191#define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */
@@ -1200,70 +1167,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8904;
1200#define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */ 1167#define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */
1201 1168
1202/* 1169/*
1203 * R121 (0x79) - GPIO Control 1
1204 */
1205#define WM8904_GPIO1_PU 0x0020 /* GPIO1_PU */
1206#define WM8904_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
1207#define WM8904_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
1208#define WM8904_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
1209#define WM8904_GPIO1_PD 0x0010 /* GPIO1_PD */
1210#define WM8904_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
1211#define WM8904_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
1212#define WM8904_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
1213#define WM8904_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
1214#define WM8904_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
1215#define WM8904_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
1216
1217/*
1218 * R122 (0x7A) - GPIO Control 2
1219 */
1220#define WM8904_GPIO2_PU 0x0020 /* GPIO2_PU */
1221#define WM8904_GPIO2_PU_MASK 0x0020 /* GPIO2_PU */
1222#define WM8904_GPIO2_PU_SHIFT 5 /* GPIO2_PU */
1223#define WM8904_GPIO2_PU_WIDTH 1 /* GPIO2_PU */
1224#define WM8904_GPIO2_PD 0x0010 /* GPIO2_PD */
1225#define WM8904_GPIO2_PD_MASK 0x0010 /* GPIO2_PD */
1226#define WM8904_GPIO2_PD_SHIFT 4 /* GPIO2_PD */
1227#define WM8904_GPIO2_PD_WIDTH 1 /* GPIO2_PD */
1228#define WM8904_GPIO2_SEL_MASK 0x000F /* GPIO2_SEL - [3:0] */
1229#define WM8904_GPIO2_SEL_SHIFT 0 /* GPIO2_SEL - [3:0] */
1230#define WM8904_GPIO2_SEL_WIDTH 4 /* GPIO2_SEL - [3:0] */
1231
1232/*
1233 * R123 (0x7B) - GPIO Control 3
1234 */
1235#define WM8904_GPIO3_PU 0x0020 /* GPIO3_PU */
1236#define WM8904_GPIO3_PU_MASK 0x0020 /* GPIO3_PU */
1237#define WM8904_GPIO3_PU_SHIFT 5 /* GPIO3_PU */
1238#define WM8904_GPIO3_PU_WIDTH 1 /* GPIO3_PU */
1239#define WM8904_GPIO3_PD 0x0010 /* GPIO3_PD */
1240#define WM8904_GPIO3_PD_MASK 0x0010 /* GPIO3_PD */
1241#define WM8904_GPIO3_PD_SHIFT 4 /* GPIO3_PD */
1242#define WM8904_GPIO3_PD_WIDTH 1 /* GPIO3_PD */
1243#define WM8904_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
1244#define WM8904_GPIO3_SEL_SHIFT 0 /* GPIO3_SEL - [3:0] */
1245#define WM8904_GPIO3_SEL_WIDTH 4 /* GPIO3_SEL - [3:0] */
1246
1247/*
1248 * R124 (0x7C) - GPIO Control 4
1249 */
1250#define WM8904_GPI7_ENA 0x0200 /* GPI7_ENA */
1251#define WM8904_GPI7_ENA_MASK 0x0200 /* GPI7_ENA */
1252#define WM8904_GPI7_ENA_SHIFT 9 /* GPI7_ENA */
1253#define WM8904_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
1254#define WM8904_GPI8_ENA 0x0100 /* GPI8_ENA */
1255#define WM8904_GPI8_ENA_MASK 0x0100 /* GPI8_ENA */
1256#define WM8904_GPI8_ENA_SHIFT 8 /* GPI8_ENA */
1257#define WM8904_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
1258#define WM8904_GPIO_BCLK_MODE_ENA 0x0080 /* GPIO_BCLK_MODE_ENA */
1259#define WM8904_GPIO_BCLK_MODE_ENA_MASK 0x0080 /* GPIO_BCLK_MODE_ENA */
1260#define WM8904_GPIO_BCLK_MODE_ENA_SHIFT 7 /* GPIO_BCLK_MODE_ENA */
1261#define WM8904_GPIO_BCLK_MODE_ENA_WIDTH 1 /* GPIO_BCLK_MODE_ENA */
1262#define WM8904_GPIO_BCLK_SEL_MASK 0x000F /* GPIO_BCLK_SEL - [3:0] */
1263#define WM8904_GPIO_BCLK_SEL_SHIFT 0 /* GPIO_BCLK_SEL - [3:0] */
1264#define WM8904_GPIO_BCLK_SEL_WIDTH 4 /* GPIO_BCLK_SEL - [3:0] */
1265
1266/*
1267 * R126 (0x7E) - Digital Pulls 1170 * R126 (0x7E) - Digital Pulls
1268 */ 1171 */
1269#define WM8904_MCLK_PU 0x0080 /* MCLK_PU */ 1172#define WM8904_MCLK_PU 0x0080 /* MCLK_PU */
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index d07bcc1e1c60..c2960d3ec6df 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -22,6 +22,7 @@
22#include <sound/soc-dapm.h> 22#include <sound/soc-dapm.h>
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/tlv.h> 24#include <sound/tlv.h>
25#include <sound/wm8960.h>
25 26
26#include "wm8960.h" 27#include "wm8960.h"
27 28
@@ -30,8 +31,14 @@
30struct snd_soc_codec_device soc_codec_dev_wm8960; 31struct snd_soc_codec_device soc_codec_dev_wm8960;
31 32
32/* R25 - Power 1 */ 33/* R25 - Power 1 */
34#define WM8960_VMID_MASK 0x180
33#define WM8960_VREF 0x40 35#define WM8960_VREF 0x40
34 36
37/* R26 - Power 2 */
38#define WM8960_PWR2_LOUT1 0x40
39#define WM8960_PWR2_ROUT1 0x20
40#define WM8960_PWR2_OUT3 0x02
41
35/* R28 - Anti-pop 1 */ 42/* R28 - Anti-pop 1 */
36#define WM8960_POBCTRL 0x80 43#define WM8960_POBCTRL 0x80
37#define WM8960_BUFDCOPEN 0x10 44#define WM8960_BUFDCOPEN 0x10
@@ -41,6 +48,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8960;
41 48
42/* R29 - Anti-pop 2 */ 49/* R29 - Anti-pop 2 */
43#define WM8960_DISOP 0x40 50#define WM8960_DISOP 0x40
51#define WM8960_DRES_MASK 0x30
44 52
45/* 53/*
46 * wm8960 register cache 54 * wm8960 register cache
@@ -67,6 +75,9 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
67struct wm8960_priv { 75struct wm8960_priv {
68 u16 reg_cache[WM8960_CACHEREGNUM]; 76 u16 reg_cache[WM8960_CACHEREGNUM];
69 struct snd_soc_codec codec; 77 struct snd_soc_codec codec;
78 struct snd_soc_dapm_widget *lout1;
79 struct snd_soc_dapm_widget *rout1;
80 struct snd_soc_dapm_widget *out3;
70}; 81};
71 82
72#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) 83#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
@@ -225,10 +236,6 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
225 &wm8960_routput_mixer[0], 236 &wm8960_routput_mixer[0],
226 ARRAY_SIZE(wm8960_routput_mixer)), 237 ARRAY_SIZE(wm8960_routput_mixer)),
227 238
228SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
229 &wm8960_mono_out[0],
230 ARRAY_SIZE(wm8960_mono_out)),
231
232SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), 239SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
233SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), 240SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
234 241
@@ -247,6 +254,17 @@ SND_SOC_DAPM_OUTPUT("SPK_RN"),
247SND_SOC_DAPM_OUTPUT("OUT3"), 254SND_SOC_DAPM_OUTPUT("OUT3"),
248}; 255};
249 256
257static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = {
258SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
259 &wm8960_mono_out[0],
260 ARRAY_SIZE(wm8960_mono_out)),
261};
262
263/* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */
264static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = {
265SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0),
266};
267
250static const struct snd_soc_dapm_route audio_paths[] = { 268static const struct snd_soc_dapm_route audio_paths[] = {
251 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, 269 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
252 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, 270 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
@@ -277,9 +295,6 @@ static const struct snd_soc_dapm_route audio_paths[] = {
277 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , 295 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
278 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, 296 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
279 297
280 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
281 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
282
283 { "LOUT1 PGA", NULL, "Left Output Mixer" }, 298 { "LOUT1 PGA", NULL, "Left Output Mixer" },
284 { "ROUT1 PGA", NULL, "Right Output Mixer" }, 299 { "ROUT1 PGA", NULL, "Right Output Mixer" },
285 300
@@ -296,17 +311,65 @@ static const struct snd_soc_dapm_route audio_paths[] = {
296 { "SPK_LP", NULL, "Left Speaker Output" }, 311 { "SPK_LP", NULL, "Left Speaker Output" },
297 { "SPK_RN", NULL, "Right Speaker Output" }, 312 { "SPK_RN", NULL, "Right Speaker Output" },
298 { "SPK_RP", NULL, "Right Speaker Output" }, 313 { "SPK_RP", NULL, "Right Speaker Output" },
314};
315
316static const struct snd_soc_dapm_route audio_paths_out3[] = {
317 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
318 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
299 319
300 { "OUT3", NULL, "Mono Output Mixer", } 320 { "OUT3", NULL, "Mono Output Mixer", }
301}; 321};
302 322
323static const struct snd_soc_dapm_route audio_paths_capless[] = {
324 { "HP_L", NULL, "OUT3 VMID" },
325 { "HP_R", NULL, "OUT3 VMID" },
326
327 { "OUT3 VMID", NULL, "Left Output Mixer" },
328 { "OUT3 VMID", NULL, "Right Output Mixer" },
329};
330
303static int wm8960_add_widgets(struct snd_soc_codec *codec) 331static int wm8960_add_widgets(struct snd_soc_codec *codec)
304{ 332{
333 struct wm8960_data *pdata = codec->dev->platform_data;
334 struct wm8960_priv *wm8960 = codec->private_data;
335 struct snd_soc_dapm_widget *w;
336
305 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, 337 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
306 ARRAY_SIZE(wm8960_dapm_widgets)); 338 ARRAY_SIZE(wm8960_dapm_widgets));
307 339
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 340 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309 341
342 /* In capless mode OUT3 is used to provide VMID for the
343 * headphone outputs, otherwise it is used as a mono mixer.
344 */
345 if (pdata && pdata->capless) {
346 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_capless,
347 ARRAY_SIZE(wm8960_dapm_widgets_capless));
348
349 snd_soc_dapm_add_routes(codec, audio_paths_capless,
350 ARRAY_SIZE(audio_paths_capless));
351 } else {
352 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_out3,
353 ARRAY_SIZE(wm8960_dapm_widgets_out3));
354
355 snd_soc_dapm_add_routes(codec, audio_paths_out3,
356 ARRAY_SIZE(audio_paths_out3));
357 }
358
359 /* We need to power up the headphone output stage out of
360 * sequence for capless mode. To save scanning the widget
361 * list each time to find the desired power state do so now
362 * and save the result.
363 */
364 list_for_each_entry(w, &codec->dapm_widgets, list) {
365 if (strcmp(w->name, "LOUT1 PGA") == 0)
366 wm8960->lout1 = w;
367 if (strcmp(w->name, "ROUT1 PGA") == 0)
368 wm8960->rout1 = w;
369 if (strcmp(w->name, "OUT3 VMID") == 0)
370 wm8960->out3 = w;
371 }
372
310 return 0; 373 return 0;
311} 374}
312 375
@@ -407,10 +470,9 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute)
407 return 0; 470 return 0;
408} 471}
409 472
410static int wm8960_set_bias_level(struct snd_soc_codec *codec, 473static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
411 enum snd_soc_bias_level level) 474 enum snd_soc_bias_level level)
412{ 475{
413 struct wm8960_data *pdata = codec->dev->platform_data;
414 u16 reg; 476 u16 reg;
415 477
416 switch (level) { 478 switch (level) {
@@ -429,18 +491,8 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
429 if (codec->bias_level == SND_SOC_BIAS_OFF) { 491 if (codec->bias_level == SND_SOC_BIAS_OFF) {
430 /* Enable anti-pop features */ 492 /* Enable anti-pop features */
431 snd_soc_write(codec, WM8960_APOP1, 493 snd_soc_write(codec, WM8960_APOP1,
432 WM8960_POBCTRL | WM8960_SOFT_ST | 494 WM8960_POBCTRL | WM8960_SOFT_ST |
433 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 495 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
434
435 /* Discharge HP output */
436 reg = WM8960_DISOP;
437 if (pdata)
438 reg |= pdata->dres << 4;
439 snd_soc_write(codec, WM8960_APOP2, reg);
440
441 msleep(400);
442
443 snd_soc_write(codec, WM8960_APOP2, 0);
444 496
445 /* Enable & ramp VMID at 2x50k */ 497 /* Enable & ramp VMID at 2x50k */
446 reg = snd_soc_read(codec, WM8960_POWER1); 498 reg = snd_soc_read(codec, WM8960_POWER1);
@@ -471,8 +523,101 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
471 /* Disable VMID and VREF, let them discharge */ 523 /* Disable VMID and VREF, let them discharge */
472 snd_soc_write(codec, WM8960_POWER1, 0); 524 snd_soc_write(codec, WM8960_POWER1, 0);
473 msleep(600); 525 msleep(600);
526 break;
527 }
528
529 codec->bias_level = level;
530
531 return 0;
532}
533
534static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
535 enum snd_soc_bias_level level)
536{
537 struct wm8960_priv *wm8960 = codec->private_data;
538 int reg;
539
540 switch (level) {
541 case SND_SOC_BIAS_ON:
542 break;
543
544 case SND_SOC_BIAS_PREPARE:
545 switch (codec->bias_level) {
546 case SND_SOC_BIAS_STANDBY:
547 /* Enable anti pop mode */
548 snd_soc_update_bits(codec, WM8960_APOP1,
549 WM8960_POBCTRL | WM8960_SOFT_ST |
550 WM8960_BUFDCOPEN,
551 WM8960_POBCTRL | WM8960_SOFT_ST |
552 WM8960_BUFDCOPEN);
553
554 /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */
555 reg = 0;
556 if (wm8960->lout1 && wm8960->lout1->power)
557 reg |= WM8960_PWR2_LOUT1;
558 if (wm8960->rout1 && wm8960->rout1->power)
559 reg |= WM8960_PWR2_ROUT1;
560 if (wm8960->out3 && wm8960->out3->power)
561 reg |= WM8960_PWR2_OUT3;
562 snd_soc_update_bits(codec, WM8960_POWER2,
563 WM8960_PWR2_LOUT1 |
564 WM8960_PWR2_ROUT1 |
565 WM8960_PWR2_OUT3, reg);
566
567 /* Enable VMID at 2*50k */
568 snd_soc_update_bits(codec, WM8960_POWER1,
569 WM8960_VMID_MASK, 0x80);
570
571 /* Ramp */
572 msleep(100);
573
574 /* Enable VREF */
575 snd_soc_update_bits(codec, WM8960_POWER1,
576 WM8960_VREF, WM8960_VREF);
577
578 msleep(100);
579 break;
580
581 case SND_SOC_BIAS_ON:
582 /* Enable anti-pop mode */
583 snd_soc_update_bits(codec, WM8960_APOP1,
584 WM8960_POBCTRL | WM8960_SOFT_ST |
585 WM8960_BUFDCOPEN,
586 WM8960_POBCTRL | WM8960_SOFT_ST |
587 WM8960_BUFDCOPEN);
588
589 /* Disable VMID and VREF */
590 snd_soc_update_bits(codec, WM8960_POWER1,
591 WM8960_VREF | WM8960_VMID_MASK, 0);
592 break;
593
594 default:
595 break;
596 }
597 break;
598
599 case SND_SOC_BIAS_STANDBY:
600 switch (codec->bias_level) {
601 case SND_SOC_BIAS_PREPARE:
602 /* Disable HP discharge */
603 snd_soc_update_bits(codec, WM8960_APOP2,
604 WM8960_DISOP | WM8960_DRES_MASK,
605 0);
606
607 /* Disable anti-pop features */
608 snd_soc_update_bits(codec, WM8960_APOP1,
609 WM8960_POBCTRL | WM8960_SOFT_ST |
610 WM8960_BUFDCOPEN,
611 WM8960_POBCTRL | WM8960_SOFT_ST |
612 WM8960_BUFDCOPEN);
613 break;
614
615 default:
616 break;
617 }
618 break;
474 619
475 snd_soc_write(codec, WM8960_APOP1, 0); 620 case SND_SOC_BIAS_OFF:
476 break; 621 break;
477 } 622 }
478 623
@@ -662,7 +807,7 @@ static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
662 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 807 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
663 struct snd_soc_codec *codec = socdev->card->codec; 808 struct snd_soc_codec *codec = socdev->card->codec;
664 809
665 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF); 810 codec->set_bias_level(codec, SND_SOC_BIAS_OFF);
666 return 0; 811 return 0;
667} 812}
668 813
@@ -681,8 +826,8 @@ static int wm8960_resume(struct platform_device *pdev)
681 codec->hw_write(codec->control_data, data, 2); 826 codec->hw_write(codec->control_data, data, 2);
682 } 827 }
683 828
684 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 829 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
685 wm8960_set_bias_level(codec, codec->suspend_bias_level); 830 codec->set_bias_level(codec, codec->suspend_bias_level);
686 return 0; 831 return 0;
687} 832}
688 833
@@ -752,6 +897,8 @@ static int wm8960_register(struct wm8960_priv *wm8960,
752 goto err; 897 goto err;
753 } 898 }
754 899
900 codec->set_bias_level = wm8960_set_bias_level_out3;
901
755 if (!pdata) { 902 if (!pdata) {
756 dev_warn(codec->dev, "No platform data supplied\n"); 903 dev_warn(codec->dev, "No platform data supplied\n");
757 } else { 904 } else {
@@ -759,6 +906,9 @@ static int wm8960_register(struct wm8960_priv *wm8960,
759 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); 906 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
760 pdata->dres = 0; 907 pdata->dres = 0;
761 } 908 }
909
910 if (pdata->capless)
911 codec->set_bias_level = wm8960_set_bias_level_capless;
762 } 912 }
763 913
764 mutex_init(&codec->mutex); 914 mutex_init(&codec->mutex);
@@ -769,7 +919,6 @@ static int wm8960_register(struct wm8960_priv *wm8960,
769 codec->name = "WM8960"; 919 codec->name = "WM8960";
770 codec->owner = THIS_MODULE; 920 codec->owner = THIS_MODULE;
771 codec->bias_level = SND_SOC_BIAS_OFF; 921 codec->bias_level = SND_SOC_BIAS_OFF;
772 codec->set_bias_level = wm8960_set_bias_level;
773 codec->dai = &wm8960_dai; 922 codec->dai = &wm8960_dai;
774 codec->num_dai = 1; 923 codec->num_dai = 1;
775 codec->reg_cache_size = WM8960_CACHEREGNUM; 924 codec->reg_cache_size = WM8960_CACHEREGNUM;
@@ -791,7 +940,7 @@ static int wm8960_register(struct wm8960_priv *wm8960,
791 940
792 wm8960_dai.dev = codec->dev; 941 wm8960_dai.dev = codec->dev;
793 942
794 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 943 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
795 944
796 /* Latch the update bits */ 945 /* Latch the update bits */
797 reg = snd_soc_read(codec, WM8960_LINVOL); 946 reg = snd_soc_read(codec, WM8960_LINVOL);
@@ -840,7 +989,7 @@ err:
840 989
841static void wm8960_unregister(struct wm8960_priv *wm8960) 990static void wm8960_unregister(struct wm8960_priv *wm8960)
842{ 991{
843 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); 992 wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
844 snd_soc_unregister_dai(&wm8960_dai); 993 snd_soc_unregister_dai(&wm8960_dai);
845 snd_soc_unregister_codec(&wm8960->codec); 994 snd_soc_unregister_codec(&wm8960->codec);
846 kfree(wm8960); 995 kfree(wm8960);
@@ -882,7 +1031,7 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
882 1031
883static struct i2c_driver wm8960_i2c_driver = { 1032static struct i2c_driver wm8960_i2c_driver = {
884 .driver = { 1033 .driver = {
885 .name = "WM8960 I2C Codec", 1034 .name = "wm8960",
886 .owner = THIS_MODULE, 1035 .owner = THIS_MODULE,
887 }, 1036 },
888 .probe = wm8960_i2c_probe, 1037 .probe = wm8960_i2c_probe,
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
index c9af56c9d9d4..d67bfe1300da 100644
--- a/sound/soc/codecs/wm8960.h
+++ b/sound/soc/codecs/wm8960.h
@@ -114,14 +114,4 @@
114extern struct snd_soc_dai wm8960_dai; 114extern struct snd_soc_dai wm8960_dai;
115extern struct snd_soc_codec_device soc_codec_dev_wm8960; 115extern struct snd_soc_codec_device soc_codec_dev_wm8960;
116 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 117#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 047ee39418c0..6bbf001f6591 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -12,15 +12,38 @@ config SND_DAVINCI_SOC_I2S
12config SND_DAVINCI_SOC_MCASP 12config SND_DAVINCI_SOC_MCASP
13 tristate 13 tristate
14 14
15config SND_DAVINCI_SOC_VCIF
16 tristate
17
15config SND_DAVINCI_SOC_EVM 18config SND_DAVINCI_SOC_EVM
16 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" 19 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
17 depends on SND_DAVINCI_SOC 20 depends on SND_DAVINCI_SOC
18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM 21 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
19 select SND_DAVINCI_SOC_I2S 22 select SND_DAVINCI_SOC_I2S
20 select SND_SOC_TLV320AIC3X 23 select SND_SOC_TLV320AIC3X
21 help 24 help
22 Say Y if you want to add support for SoC audio on TI 25 Say Y if you want to add support for SoC audio on TI
23 DaVinci DM6446 or DM355 EVM platforms. 26 DaVinci DM6446, DM355 or DM365 EVM platforms.
27
28choice
29 prompt "DM365 codec select"
30 depends on SND_DAVINCI_SOC_EVM
31 depends on MACH_DAVINCI_DM365_EVM
32 default SND_DM365_EXTERNAL_CODEC
33
34config SND_DM365_AIC3X_CODEC
35 bool "Audio Codec - AIC3101"
36 help
37 Say Y if you want to add support for AIC3101 audio codec
38
39config SND_DM365_VOICE_CODEC
40 bool "Voice Codec - CQ93VC"
41 select MFD_DAVINCI_VOICECODEC
42 select SND_DAVINCI_SOC_VCIF
43 select SND_SOC_CQ0093VC
44 help
45 Say Y if you want to add support for SoC On-chip voice codec
46endchoice
24 47
25config SND_DM6467_SOC_EVM 48config SND_DM6467_SOC_EVM
26 tristate "SoC Audio support for DaVinci DM6467 EVM" 49 tristate "SoC Audio support for DaVinci DM6467 EVM"
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index a6939d71b988..a93679d618cd 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -2,10 +2,12 @@
2snd-soc-davinci-objs := davinci-pcm.o 2snd-soc-davinci-objs := davinci-pcm.o
3snd-soc-davinci-i2s-objs := davinci-i2s.o 3snd-soc-davinci-i2s-objs := davinci-i2s.o
4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o 4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
5snd-soc-davinci-vcif-objs:= davinci-vcif.o
5 6
6obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o 7obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
7obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o 8obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
8obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o 9obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
10obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
9 11
10# DAVINCI Machine Support 12# DAVINCI Machine Support
11snd-soc-evm-objs := davinci-evm.o 13snd-soc-evm-objs := davinci-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 7ccbe6684fc2..97f74d6a33e6 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -28,10 +28,12 @@
28#include <mach/mux.h> 28#include <mach/mux.h>
29 29
30#include "../codecs/tlv320aic3x.h" 30#include "../codecs/tlv320aic3x.h"
31#include "../codecs/cq93vc.h"
31#include "../codecs/spdif_transciever.h" 32#include "../codecs/spdif_transciever.h"
32#include "davinci-pcm.h" 33#include "davinci-pcm.h"
33#include "davinci-i2s.h" 34#include "davinci-i2s.h"
34#include "davinci-mcasp.h" 35#include "davinci-mcasp.h"
36#include "davinci-vcif.h"
35 37
36#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 38#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
37 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 39 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -81,10 +83,24 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
81 return 0; 83 return 0;
82} 84}
83 85
86static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
87 struct snd_pcm_hw_params *params)
88{
89 struct snd_soc_pcm_runtime *rtd = substream->private_data;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
91
92 /* set cpu DAI configuration */
93 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
94}
95
84static struct snd_soc_ops evm_ops = { 96static struct snd_soc_ops evm_ops = {
85 .hw_params = evm_hw_params, 97 .hw_params = evm_hw_params,
86}; 98};
87 99
100static struct snd_soc_ops evm_spdif_ops = {
101 .hw_params = evm_spdif_hw_params,
102};
103
88/* davinci-evm machine dapm widgets */ 104/* davinci-evm machine dapm widgets */
89static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 105static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
90 SND_SOC_DAPM_HP("Headphone Jack", NULL), 106 SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -151,6 +167,22 @@ static struct snd_soc_dai_link evm_dai = {
151 .ops = &evm_ops, 167 .ops = &evm_ops,
152}; 168};
153 169
170static struct snd_soc_dai_link dm365_evm_dai = {
171#ifdef CONFIG_SND_DM365_AIC3X_CODEC
172 .name = "TLV320AIC3X",
173 .stream_name = "AIC3X",
174 .cpu_dai = &davinci_i2s_dai,
175 .codec_dai = &aic3x_dai,
176 .init = evm_aic3x_init,
177 .ops = &evm_ops,
178#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
179 .name = "Voice Codec - CQ93VC",
180 .stream_name = "CQ93",
181 .cpu_dai = &davinci_vcif_dai,
182 .codec_dai = &cq93vc_dai,
183#endif
184};
185
154static struct snd_soc_dai_link dm6467_evm_dai[] = { 186static struct snd_soc_dai_link dm6467_evm_dai[] = {
155 { 187 {
156 .name = "TLV320AIC3X", 188 .name = "TLV320AIC3X",
@@ -165,7 +197,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
165 .stream_name = "spdif", 197 .stream_name = "spdif",
166 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], 198 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI],
167 .codec_dai = &dit_stub_dai, 199 .codec_dai = &dit_stub_dai,
168 .ops = &evm_ops, 200 .ops = &evm_spdif_ops,
169 }, 201 },
170}; 202};
171static struct snd_soc_dai_link da8xx_evm_dai = { 203static struct snd_soc_dai_link da8xx_evm_dai = {
@@ -177,7 +209,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
177 .ops = &evm_ops, 209 .ops = &evm_ops,
178}; 210};
179 211
180/* davinci dm6446, dm355 or dm365 evm audio machine driver */ 212/* davinci dm6446, dm355 evm audio machine driver */
181static struct snd_soc_card snd_soc_card_evm = { 213static struct snd_soc_card snd_soc_card_evm = {
182 .name = "DaVinci EVM", 214 .name = "DaVinci EVM",
183 .platform = &davinci_soc_platform, 215 .platform = &davinci_soc_platform,
@@ -185,6 +217,15 @@ static struct snd_soc_card snd_soc_card_evm = {
185 .num_links = 1, 217 .num_links = 1,
186}; 218};
187 219
220/* davinci dm365 evm audio machine driver */
221static struct snd_soc_card dm365_snd_soc_card_evm = {
222 .name = "DaVinci DM365 EVM",
223 .platform = &davinci_soc_platform,
224 .dai_link = &dm365_evm_dai,
225 .num_links = 1,
226};
227
228
188/* davinci dm6467 evm audio machine driver */ 229/* davinci dm6467 evm audio machine driver */
189static struct snd_soc_card dm6467_snd_soc_card_evm = { 230static struct snd_soc_card dm6467_snd_soc_card_evm = {
190 .name = "DaVinci DM6467 EVM", 231 .name = "DaVinci DM6467 EVM",
@@ -217,6 +258,17 @@ static struct snd_soc_device evm_snd_devdata = {
217}; 258};
218 259
219/* evm audio subsystem */ 260/* evm audio subsystem */
261static struct snd_soc_device dm365_evm_snd_devdata = {
262 .card = &dm365_snd_soc_card_evm,
263#ifdef CONFIG_SND_DM365_AIC3X_CODEC
264 .codec_dev = &soc_codec_dev_aic3x,
265 .codec_data = &aic3x_setup,
266#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
267 .codec_dev = &soc_codec_dev_cq93vc,
268#endif
269};
270
271/* evm audio subsystem */
220static struct snd_soc_device dm6467_evm_snd_devdata = { 272static struct snd_soc_device dm6467_evm_snd_devdata = {
221 .card = &dm6467_snd_soc_card_evm, 273 .card = &dm6467_snd_soc_card_evm,
222 .codec_dev = &soc_codec_dev_aic3x, 274 .codec_dev = &soc_codec_dev_aic3x,
@@ -244,12 +296,15 @@ static int __init evm_init(void)
244 int index; 296 int index;
245 int ret; 297 int ret;
246 298
247 if (machine_is_davinci_evm() || machine_is_davinci_dm365_evm()) { 299 if (machine_is_davinci_evm()) {
248 evm_snd_dev_data = &evm_snd_devdata; 300 evm_snd_dev_data = &evm_snd_devdata;
249 index = 0; 301 index = 0;
250 } else if (machine_is_davinci_dm355_evm()) { 302 } else if (machine_is_davinci_dm355_evm()) {
251 evm_snd_dev_data = &evm_snd_devdata; 303 evm_snd_dev_data = &evm_snd_devdata;
252 index = 1; 304 index = 1;
305 } else if (machine_is_davinci_dm365_evm()) {
306 evm_snd_dev_data = &dm365_evm_snd_devdata;
307 index = 0;
253 } else if (machine_is_davinci_dm6467_evm()) { 308 } else if (machine_is_davinci_dm6467_evm()) {
254 evm_snd_dev_data = &dm6467_evm_snd_devdata; 309 evm_snd_dev_data = &dm6467_evm_snd_devdata;
255 index = 0; 310 index = 0;
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 6362ca05506e..4aad7ecc90a2 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -585,7 +585,8 @@ static int davinci_i2s_probe(struct platform_device *pdev)
585 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 585 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
586 586
587 davinci_i2s_dai.private_data = dev; 587 davinci_i2s_dai.private_data = dev;
588 davinci_i2s_dai.dma_data = dev->dma_params; 588 davinci_i2s_dai.capture.dma_data = dev->dma_params;
589 davinci_i2s_dai.playback.dma_data = dev->dma_params;
589 ret = snd_soc_register_dai(&davinci_i2s_dai); 590 ret = snd_soc_register_dai(&davinci_i2s_dai);
590 if (ret != 0) 591 if (ret != 0)
591 goto err_free_mem; 592 goto err_free_mem;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index ab6518d86f18..c056bfbe0340 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -917,7 +917,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
917 917
918 dma_data->channel = res->start; 918 dma_data->channel = res->start;
919 davinci_mcasp_dai[pdata->op_mode].private_data = dev; 919 davinci_mcasp_dai[pdata->op_mode].private_data = dev;
920 davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params; 920 davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params;
921 davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params;
921 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; 922 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
922 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); 923 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
923 924
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 80c7fdf2f521..2dc406f42fe7 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -649,8 +649,10 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
649 struct snd_pcm_hardware *ppcm; 649 struct snd_pcm_hardware *ppcm;
650 int ret = 0; 650 int ret = 0;
651 struct snd_soc_pcm_runtime *rtd = substream->private_data; 651 struct snd_soc_pcm_runtime *rtd = substream->private_data;
652 struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data; 652 struct davinci_pcm_dma_params *pa;
653 struct davinci_pcm_dma_params *params; 653 struct davinci_pcm_dma_params *params;
654
655 pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
654 if (!pa) 656 if (!pa)
655 return -ENODEV; 657 return -ENODEV;
656 params = &pa[substream->stream]; 658 params = &pa[substream->stream];
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
new file mode 100644
index 000000000000..54b91e1768c4
--- /dev/null
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -0,0 +1,273 @@
1/*
2 * ALSA SoC Voice Codec Interface for TI DAVINCI processor
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/device.h>
26#include <linux/delay.h>
27#include <linux/io.h>
28#include <linux/mfd/davinci_voicecodec.h>
29
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/initval.h>
34#include <sound/soc.h>
35
36#include "davinci-pcm.h"
37#include "davinci-i2s.h"
38#include "davinci-vcif.h"
39
40#define MOD_REG_BIT(val, mask, set) do { \
41 if (set) { \
42 val |= mask; \
43 } else { \
44 val &= ~mask; \
45 } \
46} while (0)
47
48struct davinci_vcif_dev {
49 struct davinci_vc *davinci_vc;
50 struct davinci_pcm_dma_params dma_params[2];
51};
52
53static void davinci_vcif_start(struct snd_pcm_substream *substream)
54{
55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
56 struct davinci_vcif_dev *davinci_vcif_dev =
57 rtd->dai->cpu_dai->private_data;
58 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
59 u32 w;
60
61 /* Start the sample generator and enable transmitter/receiver */
62 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
63
64 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
65 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
66 else
67 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
68
69 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
70}
71
72static void davinci_vcif_stop(struct snd_pcm_substream *substream)
73{
74 struct snd_soc_pcm_runtime *rtd = substream->private_data;
75 struct davinci_vcif_dev *davinci_vcif_dev =
76 rtd->dai->cpu_dai->private_data;
77 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
78 u32 w;
79
80 /* Reset transmitter/receiver and sample rate/frame sync generators */
81 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
82 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
83 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
84 else
85 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
86
87 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
88}
89
90static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
91 struct snd_pcm_hw_params *params,
92 struct snd_soc_dai *dai)
93{
94 struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data;
95 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
96 struct davinci_pcm_dma_params *dma_params =
97 &davinci_vcif_dev->dma_params[substream->stream];
98 u32 w;
99
100 /* Restart the codec before setup */
101 davinci_vcif_stop(substream);
102 davinci_vcif_start(substream);
103
104 /* General line settings */
105 writel(DAVINCI_VC_CTRL_MASK, davinci_vc->base + DAVINCI_VC_CTRL);
106
107 writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTCLR);
108
109 writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTEN);
110
111 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
112
113 /* Determine xfer data type */
114 switch (params_format(params)) {
115 case SNDRV_PCM_FORMAT_U8:
116 dma_params->data_type = 0;
117
118 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
119 DAVINCI_VC_CTRL_RD_UNSIGNED |
120 DAVINCI_VC_CTRL_WD_BITS_8 |
121 DAVINCI_VC_CTRL_WD_UNSIGNED, 1);
122 break;
123 case SNDRV_PCM_FORMAT_S8:
124 dma_params->data_type = 1;
125
126 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
127 DAVINCI_VC_CTRL_WD_BITS_8, 1);
128
129 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_UNSIGNED |
130 DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
131 break;
132 case SNDRV_PCM_FORMAT_S16_LE:
133 dma_params->data_type = 2;
134
135 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
136 DAVINCI_VC_CTRL_RD_UNSIGNED |
137 DAVINCI_VC_CTRL_WD_BITS_8 |
138 DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
139 break;
140 default:
141 printk(KERN_WARNING "davinci-vcif: unsupported PCM format");
142 return -EINVAL;
143 }
144
145 dma_params->acnt = dma_params->data_type;
146
147 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
148
149 return 0;
150}
151
152static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
153 struct snd_soc_dai *dai)
154{
155 int ret = 0;
156
157 switch (cmd) {
158 case SNDRV_PCM_TRIGGER_START:
159 case SNDRV_PCM_TRIGGER_RESUME:
160 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
161 davinci_vcif_start(substream);
162 case SNDRV_PCM_TRIGGER_STOP:
163 case SNDRV_PCM_TRIGGER_SUSPEND:
164 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
165 davinci_vcif_stop(substream);
166 break;
167 default:
168 ret = -EINVAL;
169 }
170
171 return ret;
172}
173
174#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
175
176static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
177 .trigger = davinci_vcif_trigger,
178 .hw_params = davinci_vcif_hw_params,
179};
180
181struct snd_soc_dai davinci_vcif_dai = {
182 .name = "davinci-vcif",
183 .playback = {
184 .channels_min = 1,
185 .channels_max = 2,
186 .rates = DAVINCI_VCIF_RATES,
187 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
188 .capture = {
189 .channels_min = 1,
190 .channels_max = 2,
191 .rates = DAVINCI_VCIF_RATES,
192 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
193 .ops = &davinci_vcif_dai_ops,
194
195};
196EXPORT_SYMBOL_GPL(davinci_vcif_dai);
197
198static int davinci_vcif_probe(struct platform_device *pdev)
199{
200 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
201 struct davinci_vcif_dev *davinci_vcif_dev;
202 int ret;
203
204 davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL);
205 if (!davinci_vc) {
206 dev_dbg(&pdev->dev,
207 "could not allocate memory for private data\n");
208 return -ENOMEM;
209 }
210
211 /* DMA tx params */
212 davinci_vcif_dev->davinci_vc = davinci_vc;
213 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel =
214 davinci_vc->davinci_vcif.dma_tx_channel;
215 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
216 davinci_vc->davinci_vcif.dma_tx_addr;
217
218 /* DMA rx params */
219 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel =
220 davinci_vc->davinci_vcif.dma_rx_channel;
221 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
222 davinci_vc->davinci_vcif.dma_rx_addr;
223
224 davinci_vcif_dai.dev = &pdev->dev;
225 davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params;
226 davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params;
227 davinci_vcif_dai.private_data = davinci_vcif_dev;
228
229 ret = snd_soc_register_dai(&davinci_vcif_dai);
230 if (ret != 0) {
231 dev_err(&pdev->dev, "could not register dai\n");
232 goto fail;
233 }
234
235 return 0;
236
237fail:
238 kfree(davinci_vcif_dev);
239
240 return ret;
241}
242
243static int davinci_vcif_remove(struct platform_device *pdev)
244{
245 snd_soc_unregister_dai(&davinci_vcif_dai);
246
247 return 0;
248}
249
250static struct platform_driver davinci_vcif_driver = {
251 .probe = davinci_vcif_probe,
252 .remove = davinci_vcif_remove,
253 .driver = {
254 .name = "davinci_vcif",
255 .owner = THIS_MODULE,
256 },
257};
258
259static int __init davinci_vcif_init(void)
260{
261 return platform_driver_probe(&davinci_vcif_driver, davinci_vcif_probe);
262}
263module_init(davinci_vcif_init);
264
265static void __exit davinci_vcif_exit(void)
266{
267 platform_driver_unregister(&davinci_vcif_driver);
268}
269module_exit(davinci_vcif_exit);
270
271MODULE_AUTHOR("Miguel Aguilar");
272MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface");
273MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h
new file mode 100644
index 000000000000..571c9948724f
--- /dev/null
+++ b/sound/soc/davinci/davinci-vcif.h
@@ -0,0 +1,28 @@
1/*
2 * ALSA SoC Voice Codec Interface for TI DAVINCI processor
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _DAVINCI_VCIF_H
24#define _DAVINCI_VCIF_H
25
26extern struct snd_soc_dai davinci_vcif_dai;
27
28#endif
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 7174b4c710de..eba9b9d257a1 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -11,3 +11,11 @@ config SND_IMX_SOC
11config SND_MXC_SOC_SSI 11config SND_MXC_SOC_SSI
12 tristate 12 tristate
13 13
14config SND_MXC_SOC_WM1133_EV1
15 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
16 depends on SND_IMX_SOC && EXPERIMENTAL
17 select SND_SOC_WM8350
18 select SND_MXC_SOC_SSI
19 help
20 Enable support for audio on the i.MX31ADS with the WM1133-EV1
21 PMIC board with WM8835x fitted.
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index 9f8bb92ddfcc..2d203635ac11 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -9,4 +9,7 @@ obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
9 9
10# i.MX Machine Support 10# i.MX Machine Support
11snd-soc-phycore-ac97-objs := phycore-ac97.o 11snd-soc-phycore-ac97-objs := phycore-ac97.o
12snd-soc-wm1133-ev1-objs := wm1133-ev1.o
13
12obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o 14obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
15obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 19452e44afdc..c78c000e2afe 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -83,11 +83,13 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
83static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) 83static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
84{ 84{
85 struct snd_soc_pcm_runtime *rtd = substream->private_data; 85 struct snd_soc_pcm_runtime *rtd = substream->private_data;
86 struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; 86 struct imx_pcm_dma_params *dma_params;
87 struct snd_pcm_runtime *runtime = substream->runtime; 87 struct snd_pcm_runtime *runtime = substream->runtime;
88 struct imx_pcm_runtime_data *iprtd = runtime->private_data; 88 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
89 int ret; 89 int ret;
90 90
91 dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
92
91 iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); 93 iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
92 if (iprtd->dma < 0) { 94 if (iprtd->dma < 0) {
93 pr_err("Failed to claim the audio DMA\n"); 95 pr_err("Failed to claim the audio DMA\n");
@@ -192,10 +194,12 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
192{ 194{
193 struct snd_pcm_runtime *runtime = substream->runtime; 195 struct snd_pcm_runtime *runtime = substream->runtime;
194 struct snd_soc_pcm_runtime *rtd = substream->private_data; 196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
195 struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; 197 struct imx_pcm_dma_params *dma_params;
196 struct imx_pcm_runtime_data *iprtd = runtime->private_data; 198 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
197 int err; 199 int err;
198 200
201 dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
202
199 iprtd->substream = substream; 203 iprtd->substream = substream;
200 iprtd->buf = (unsigned int *)substream->dma_buffer.area; 204 iprtd->buf = (unsigned int *)substream->dma_buffer.area;
201 iprtd->period_cnt = 0; 205 iprtd->period_cnt = 0;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 56f46a75d297..28e55c7b14b4 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -234,17 +234,20 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
234 struct snd_soc_dai *cpu_dai) 234 struct snd_soc_dai *cpu_dai)
235{ 235{
236 struct imx_ssi *ssi = cpu_dai->private_data; 236 struct imx_ssi *ssi = cpu_dai->private_data;
237 struct imx_pcm_dma_params *dma_data;
237 u32 reg, sccr; 238 u32 reg, sccr;
238 239
239 /* Tx/Rx config */ 240 /* Tx/Rx config */
240 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 241 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
241 reg = SSI_STCCR; 242 reg = SSI_STCCR;
242 cpu_dai->dma_data = &ssi->dma_params_tx; 243 dma_data = &ssi->dma_params_tx;
243 } else { 244 } else {
244 reg = SSI_SRCCR; 245 reg = SSI_SRCCR;
245 cpu_dai->dma_data = &ssi->dma_params_rx; 246 dma_data = &ssi->dma_params_rx;
246 } 247 }
247 248
249 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
250
248 sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; 251 sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
249 252
250 /* DAI data (word) size */ 253 /* DAI data (word) size */
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
new file mode 100644
index 000000000000..a6e7d9497639
--- /dev/null
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -0,0 +1,308 @@
1/*
2 * wm1133-ev1.c - Audio for WM1133-EV1 on i.MX31ADS
3 *
4 * Copyright (c) 2010 Wolfson Microelectronics plc
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 *
7 * Based on an earlier driver for the same hardware by Liam Girdwood.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/platform_device.h>
16#include <linux/clk.h>
17#include <sound/core.h>
18#include <sound/jack.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23
24#include <mach/audmux.h>
25
26#include "imx-ssi.h"
27#include "../codecs/wm8350.h"
28
29/* There is a silicon mic on the board optionally connected via a solder pad
30 * SP1. Define this to enable it.
31 */
32#undef USE_SIMIC
33
34struct _wm8350_audio {
35 unsigned int channels;
36 snd_pcm_format_t format;
37 unsigned int rate;
38 unsigned int sysclk;
39 unsigned int bclkdiv;
40 unsigned int clkdiv;
41 unsigned int lr_rate;
42};
43
44/* in order of power consumption per rate (lowest first) */
45static const struct _wm8350_audio wm8350_audio[] = {
46 /* 16bit mono modes */
47 {1, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000 >> 1,
48 WM8350_BCLK_DIV_48, WM8350_DACDIV_3, 16,},
49
50 /* 16 bit stereo modes */
51 {2, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000,
52 WM8350_BCLK_DIV_48, WM8350_DACDIV_6, 32,},
53 {2, SNDRV_PCM_FORMAT_S16_LE, 16000, 12288000,
54 WM8350_BCLK_DIV_24, WM8350_DACDIV_3, 32,},
55 {2, SNDRV_PCM_FORMAT_S16_LE, 32000, 12288000,
56 WM8350_BCLK_DIV_12, WM8350_DACDIV_1_5, 32,},
57 {2, SNDRV_PCM_FORMAT_S16_LE, 48000, 12288000,
58 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
59 {2, SNDRV_PCM_FORMAT_S16_LE, 96000, 24576000,
60 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
61 {2, SNDRV_PCM_FORMAT_S16_LE, 11025, 11289600,
62 WM8350_BCLK_DIV_32, WM8350_DACDIV_4, 32,},
63 {2, SNDRV_PCM_FORMAT_S16_LE, 22050, 11289600,
64 WM8350_BCLK_DIV_16, WM8350_DACDIV_2, 32,},
65 {2, SNDRV_PCM_FORMAT_S16_LE, 44100, 11289600,
66 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
67 {2, SNDRV_PCM_FORMAT_S16_LE, 88200, 22579200,
68 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
69
70 /* 24bit stereo modes */
71 {2, SNDRV_PCM_FORMAT_S24_LE, 48000, 12288000,
72 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
73 {2, SNDRV_PCM_FORMAT_S24_LE, 96000, 24576000,
74 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
75 {2, SNDRV_PCM_FORMAT_S24_LE, 44100, 11289600,
76 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
77 {2, SNDRV_PCM_FORMAT_S24_LE, 88200, 22579200,
78 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
79};
80
81static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream,
82 struct snd_pcm_hw_params *params)
83{
84 struct snd_soc_pcm_runtime *rtd = substream->private_data;
85 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
86 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
87 int i, found = 0;
88 snd_pcm_format_t format = params_format(params);
89 unsigned int rate = params_rate(params);
90 unsigned int channels = params_channels(params);
91 u32 dai_format;
92
93 /* find the correct audio parameters */
94 for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) {
95 if (rate == wm8350_audio[i].rate &&
96 format == wm8350_audio[i].format &&
97 channels == wm8350_audio[i].channels) {
98 found = 1;
99 break;
100 }
101 }
102 if (!found)
103 return -EINVAL;
104
105 /* codec FLL input is 14.75 MHz from MCLK */
106 snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk);
107
108 dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
109 SND_SOC_DAIFMT_CBM_CFM;
110
111 /* set codec DAI configuration */
112 snd_soc_dai_set_fmt(codec_dai, dai_format);
113
114 /* set cpu DAI configuration */
115 snd_soc_dai_set_fmt(cpu_dai, dai_format);
116
117 /* TODO: The SSI driver should figure this out for us */
118 switch (channels) {
119 case 2:
120 snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
121 break;
122 case 1:
123 snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0);
124 break;
125 default:
126 return -EINVAL;
127 }
128
129 /* set MCLK as the codec system clock for DAC and ADC */
130 snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_MCLK,
131 wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN);
132
133 /* set codec BCLK division for sample rate */
134 snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV,
135 wm8350_audio[i].bclkdiv);
136
137 /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */
138 snd_soc_dai_set_clkdiv(codec_dai,
139 WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate);
140 snd_soc_dai_set_clkdiv(codec_dai,
141 WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate);
142
143 /* now configure DAC and ADC clocks */
144 snd_soc_dai_set_clkdiv(codec_dai,
145 WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv);
146
147 snd_soc_dai_set_clkdiv(codec_dai,
148 WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv);
149
150 return 0;
151}
152
153static struct snd_soc_ops wm1133_ev1_ops = {
154 .hw_params = wm1133_ev1_hw_params,
155};
156
157static const struct snd_soc_dapm_widget wm1133_ev1_widgets[] = {
158#ifdef USE_SIMIC
159 SND_SOC_DAPM_MIC("SiMIC", NULL),
160#endif
161 SND_SOC_DAPM_MIC("Mic1 Jack", NULL),
162 SND_SOC_DAPM_MIC("Mic2 Jack", NULL),
163 SND_SOC_DAPM_LINE("Line In Jack", NULL),
164 SND_SOC_DAPM_LINE("Line Out Jack", NULL),
165 SND_SOC_DAPM_HP("Headphone Jack", NULL),
166};
167
168/* imx32ads soc_card audio map */
169static const struct snd_soc_dapm_route wm1133_ev1_map[] = {
170
171#ifdef USE_SIMIC
172 /* SiMIC --> IN1LN (with automatic bias) via SP1 */
173 { "IN1LN", NULL, "Mic Bias" },
174 { "Mic Bias", NULL, "SiMIC" },
175#endif
176
177 /* Mic 1 Jack --> IN1LN and IN1LP (with automatic bias) */
178 { "IN1LN", NULL, "Mic Bias" },
179 { "IN1LP", NULL, "Mic1 Jack" },
180 { "Mic Bias", NULL, "Mic1 Jack" },
181
182 /* Mic 2 Jack --> IN1RN and IN1RP (with automatic bias) */
183 { "IN1RN", NULL, "Mic Bias" },
184 { "IN1RP", NULL, "Mic2 Jack" },
185 { "Mic Bias", NULL, "Mic2 Jack" },
186
187 /* Line in Jack --> AUX (L+R) */
188 { "IN3R", NULL, "Line In Jack" },
189 { "IN3L", NULL, "Line In Jack" },
190
191 /* Out1 --> Headphone Jack */
192 { "Headphone Jack", NULL, "OUT1R" },
193 { "Headphone Jack", NULL, "OUT1L" },
194
195 /* Out1 --> Line Out Jack */
196 { "Line Out Jack", NULL, "OUT2R" },
197 { "Line Out Jack", NULL, "OUT2L" },
198};
199
200static struct snd_soc_jack hp_jack;
201
202static struct snd_soc_jack_pin hp_jack_pins[] = {
203 { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE },
204};
205
206static struct snd_soc_jack mic_jack;
207
208static struct snd_soc_jack_pin mic_jack_pins[] = {
209 { .pin = "Mic1 Jack", .mask = SND_JACK_MICROPHONE },
210 { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE },
211};
212
213static int wm1133_ev1_init(struct snd_soc_codec *codec)
214{
215 struct snd_soc_card *card = codec->socdev->card;
216
217 snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets,
218 ARRAY_SIZE(wm1133_ev1_widgets));
219
220 snd_soc_dapm_add_routes(codec, wm1133_ev1_map,
221 ARRAY_SIZE(wm1133_ev1_map));
222
223 /* Headphone jack detection */
224 snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
225 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
226 hp_jack_pins);
227 wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
228
229 /* Microphone jack detection */
230 snd_soc_jack_new(card, "Microphone",
231 SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);
232 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
233 mic_jack_pins);
234 wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE,
235 SND_JACK_BTN_0);
236
237 snd_soc_dapm_force_enable_pin(codec, "Mic Bias");
238
239 return 0;
240}
241
242
243static struct snd_soc_dai_link wm1133_ev1_dai = {
244 .name = "WM1133-EV1",
245 .stream_name = "Audio",
246 .cpu_dai = &imx_ssi_pcm_dai[0],
247 .codec_dai = &wm8350_dai,
248 .init = wm1133_ev1_init,
249 .ops = &wm1133_ev1_ops,
250 .symmetric_rates = 1,
251};
252
253static struct snd_soc_card wm1133_ev1 = {
254 .name = "WM1133-EV1",
255 .platform = &imx_soc_platform,
256 .dai_link = &wm1133_ev1_dai,
257 .num_links = 1,
258};
259
260static struct snd_soc_device wm1133_ev1_snd_devdata = {
261 .card = &wm1133_ev1,
262 .codec_dev = &soc_codec_dev_wm8350,
263};
264
265static struct platform_device *wm1133_ev1_snd_device;
266
267static int __init wm1133_ev1_audio_init(void)
268{
269 int ret;
270 unsigned int ptcr, pdcr;
271
272 /* SSI0 mastered by port 5 */
273 ptcr = MXC_AUDMUX_V2_PTCR_SYN |
274 MXC_AUDMUX_V2_PTCR_TFSDIR |
275 MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
276 MXC_AUDMUX_V2_PTCR_TCLKDIR |
277 MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
278 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
279 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
280
281 ptcr = MXC_AUDMUX_V2_PTCR_SYN;
282 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
283 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
284
285 wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
286 if (!wm1133_ev1_snd_device)
287 return -ENOMEM;
288
289 platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata);
290 wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev;
291 ret = platform_device_add(wm1133_ev1_snd_device);
292
293 if (ret)
294 platform_device_put(wm1133_ev1_snd_device);
295
296 return ret;
297}
298module_init(wm1133_ev1_audio_init);
299
300static void __exit wm1133_ev1_audio_exit(void)
301{
302 platform_device_unregister(wm1133_ev1_snd_device);
303}
304module_exit(wm1133_ev1_audio_exit);
305
306MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
307MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS");
308MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
index ad8df6cfae88..479d3b6306d7 100644
--- a/sound/soc/omap/mcpdm.c
+++ b/sound/soc/omap/mcpdm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * mcpdm.c -- McPDM interface driver 2 * mcpdm.c -- McPDM interface driver
3 * 3 *
4 * Author: Jorge Eduardo Candelaria <x0107209@ti.com> 4 * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
5 * Copyright (C) 2009 - Texas Instruments, Inc. 5 * Copyright (C) 2009 - Texas Instruments, Inc.
@@ -38,46 +38,46 @@ static struct omap_mcpdm *mcpdm;
38 38
39static inline void omap_mcpdm_write(u16 reg, u32 val) 39static inline void omap_mcpdm_write(u16 reg, u32 val)
40{ 40{
41 __raw_writel(val, mcpdm->io_base + reg); 41 __raw_writel(val, mcpdm->io_base + reg);
42} 42}
43 43
44static inline int omap_mcpdm_read(u16 reg) 44static inline int omap_mcpdm_read(u16 reg)
45{ 45{
46 return __raw_readl(mcpdm->io_base + reg); 46 return __raw_readl(mcpdm->io_base + reg);
47} 47}
48 48
49static void omap_mcpdm_reg_dump(void) 49static void omap_mcpdm_reg_dump(void)
50{ 50{
51 dev_dbg(mcpdm->dev, "***********************\n"); 51 dev_dbg(mcpdm->dev, "***********************\n");
52 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", 52 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
53 omap_mcpdm_read(MCPDM_IRQSTATUS_RAW)); 53 omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
54 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", 54 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
55 omap_mcpdm_read(MCPDM_IRQSTATUS)); 55 omap_mcpdm_read(MCPDM_IRQSTATUS));
56 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", 56 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
57 omap_mcpdm_read(MCPDM_IRQENABLE_SET)); 57 omap_mcpdm_read(MCPDM_IRQENABLE_SET));
58 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", 58 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
59 omap_mcpdm_read(MCPDM_IRQENABLE_CLR)); 59 omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
60 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", 60 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
61 omap_mcpdm_read(MCPDM_IRQWAKE_EN)); 61 omap_mcpdm_read(MCPDM_IRQWAKE_EN));
62 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", 62 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
63 omap_mcpdm_read(MCPDM_DMAENABLE_SET)); 63 omap_mcpdm_read(MCPDM_DMAENABLE_SET));
64 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", 64 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
65 omap_mcpdm_read(MCPDM_DMAENABLE_CLR)); 65 omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
66 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", 66 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
67 omap_mcpdm_read(MCPDM_DMAWAKEEN)); 67 omap_mcpdm_read(MCPDM_DMAWAKEEN));
68 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", 68 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
69 omap_mcpdm_read(MCPDM_CTRL)); 69 omap_mcpdm_read(MCPDM_CTRL));
70 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", 70 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
71 omap_mcpdm_read(MCPDM_DN_DATA)); 71 omap_mcpdm_read(MCPDM_DN_DATA));
72 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", 72 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
73 omap_mcpdm_read(MCPDM_UP_DATA)); 73 omap_mcpdm_read(MCPDM_UP_DATA));
74 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", 74 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
75 omap_mcpdm_read(MCPDM_FIFO_CTRL_DN)); 75 omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
76 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", 76 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
77 omap_mcpdm_read(MCPDM_FIFO_CTRL_UP)); 77 omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
78 dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n", 78 dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
79 omap_mcpdm_read(MCPDM_DN_OFFSET)); 79 omap_mcpdm_read(MCPDM_DN_OFFSET));
80 dev_dbg(mcpdm->dev, "***********************\n"); 80 dev_dbg(mcpdm->dev, "***********************\n");
81} 81}
82 82
83/* 83/*
@@ -86,26 +86,26 @@ static void omap_mcpdm_reg_dump(void)
86 */ 86 */
87static void omap_mcpdm_reset_capture(int reset) 87static void omap_mcpdm_reset_capture(int reset)
88{ 88{
89 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 89 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
90 90
91 if (reset) 91 if (reset)
92 ctrl |= SW_UP_RST; 92 ctrl |= SW_UP_RST;
93 else 93 else
94 ctrl &= ~SW_UP_RST; 94 ctrl &= ~SW_UP_RST;
95 95
96 omap_mcpdm_write(MCPDM_CTRL, ctrl); 96 omap_mcpdm_write(MCPDM_CTRL, ctrl);
97} 97}
98 98
99static void omap_mcpdm_reset_playback(int reset) 99static void omap_mcpdm_reset_playback(int reset)
100{ 100{
101 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 101 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
102 102
103 if (reset) 103 if (reset)
104 ctrl |= SW_DN_RST; 104 ctrl |= SW_DN_RST;
105 else 105 else
106 ctrl &= ~SW_DN_RST; 106 ctrl &= ~SW_DN_RST;
107 107
108 omap_mcpdm_write(MCPDM_CTRL, ctrl); 108 omap_mcpdm_write(MCPDM_CTRL, ctrl);
109} 109}
110 110
111/* 111/*
@@ -114,14 +114,14 @@ static void omap_mcpdm_reset_playback(int reset)
114 */ 114 */
115void omap_mcpdm_start(int stream) 115void omap_mcpdm_start(int stream)
116{ 116{
117 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 117 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
118 118
119 if (stream) 119 if (stream)
120 ctrl |= mcpdm->up_channels; 120 ctrl |= mcpdm->up_channels;
121 else 121 else
122 ctrl |= mcpdm->dn_channels; 122 ctrl |= mcpdm->dn_channels;
123 123
124 omap_mcpdm_write(MCPDM_CTRL, ctrl); 124 omap_mcpdm_write(MCPDM_CTRL, ctrl);
125} 125}
126 126
127/* 127/*
@@ -130,14 +130,14 @@ void omap_mcpdm_start(int stream)
130 */ 130 */
131void omap_mcpdm_stop(int stream) 131void omap_mcpdm_stop(int stream)
132{ 132{
133 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 133 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
134 134
135 if (stream) 135 if (stream)
136 ctrl &= ~mcpdm->up_channels; 136 ctrl &= ~mcpdm->up_channels;
137 else 137 else
138 ctrl &= ~mcpdm->dn_channels; 138 ctrl &= ~mcpdm->dn_channels;
139 139
140 omap_mcpdm_write(MCPDM_CTRL, ctrl); 140 omap_mcpdm_write(MCPDM_CTRL, ctrl);
141} 141}
142 142
143/* 143/*
@@ -146,38 +146,38 @@ void omap_mcpdm_stop(int stream)
146 */ 146 */
147int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink) 147int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
148{ 148{
149 int irq_mask = 0; 149 int irq_mask = 0;
150 int ctrl; 150 int ctrl;
151 151
152 if (!uplink) 152 if (!uplink)
153 return -EINVAL; 153 return -EINVAL;
154 154
155 mcpdm->uplink = uplink; 155 mcpdm->uplink = uplink;
156 156
157 /* Enable irq request generation */ 157 /* Enable irq request generation */
158 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; 158 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
159 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); 159 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
160 160
161 /* Configure uplink threshold */ 161 /* Configure uplink threshold */
162 if (uplink->threshold > UP_THRES_MAX) 162 if (uplink->threshold > UP_THRES_MAX)
163 uplink->threshold = UP_THRES_MAX; 163 uplink->threshold = UP_THRES_MAX;
164 164
165 omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold); 165 omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
166 166
167 /* Configure DMA controller */ 167 /* Configure DMA controller */
168 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE); 168 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
169 169
170 /* Set pdm out format */ 170 /* Set pdm out format */
171 ctrl = omap_mcpdm_read(MCPDM_CTRL); 171 ctrl = omap_mcpdm_read(MCPDM_CTRL);
172 ctrl &= ~PDMOUTFORMAT; 172 ctrl &= ~PDMOUTFORMAT;
173 ctrl |= uplink->format & PDMOUTFORMAT; 173 ctrl |= uplink->format & PDMOUTFORMAT;
174 174
175 /* Uplink channels */ 175 /* Uplink channels */
176 mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK); 176 mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
177 177
178 omap_mcpdm_write(MCPDM_CTRL, ctrl); 178 omap_mcpdm_write(MCPDM_CTRL, ctrl);
179 179
180 return 0; 180 return 0;
181} 181}
182 182
183/* 183/*
@@ -186,38 +186,38 @@ int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
186 */ 186 */
187int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink) 187int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
188{ 188{
189 int irq_mask = 0; 189 int irq_mask = 0;
190 int ctrl; 190 int ctrl;
191 191
192 if (!downlink) 192 if (!downlink)
193 return -EINVAL; 193 return -EINVAL;
194 194
195 mcpdm->downlink = downlink; 195 mcpdm->downlink = downlink;
196 196
197 /* Enable irq request generation */ 197 /* Enable irq request generation */
198 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; 198 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
199 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); 199 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
200 200
201 /* Configure uplink threshold */ 201 /* Configure uplink threshold */
202 if (downlink->threshold > DN_THRES_MAX) 202 if (downlink->threshold > DN_THRES_MAX)
203 downlink->threshold = DN_THRES_MAX; 203 downlink->threshold = DN_THRES_MAX;
204 204
205 omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold); 205 omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
206 206
207 /* Enable DMA request generation */ 207 /* Enable DMA request generation */
208 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE); 208 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
209 209
210 /* Set pdm out format */ 210 /* Set pdm out format */
211 ctrl = omap_mcpdm_read(MCPDM_CTRL); 211 ctrl = omap_mcpdm_read(MCPDM_CTRL);
212 ctrl &= ~PDMOUTFORMAT; 212 ctrl &= ~PDMOUTFORMAT;
213 ctrl |= downlink->format & PDMOUTFORMAT; 213 ctrl |= downlink->format & PDMOUTFORMAT;
214 214
215 /* Downlink channels */ 215 /* Downlink channels */
216 mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK); 216 mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
217 217
218 omap_mcpdm_write(MCPDM_CTRL, ctrl); 218 omap_mcpdm_write(MCPDM_CTRL, ctrl);
219 219
220 return 0; 220 return 0;
221} 221}
222 222
223/* 223/*
@@ -226,24 +226,24 @@ int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
226 */ 226 */
227int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink) 227int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
228{ 228{
229 int irq_mask = 0; 229 int irq_mask = 0;
230 230
231 if (!uplink) 231 if (!uplink)
232 return -EINVAL; 232 return -EINVAL;
233 233
234 /* Disable irq request generation */ 234 /* Disable irq request generation */
235 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; 235 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
236 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); 236 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
237 237
238 /* Disable DMA request generation */ 238 /* Disable DMA request generation */
239 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE); 239 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
240 240
241 /* Clear Downlink channels */ 241 /* Clear Downlink channels */
242 mcpdm->up_channels = 0; 242 mcpdm->up_channels = 0;
243 243
244 mcpdm->uplink = NULL; 244 mcpdm->uplink = NULL;
245 245
246 return 0; 246 return 0;
247} 247}
248 248
249/* 249/*
@@ -252,124 +252,124 @@ int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
252 */ 252 */
253int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink) 253int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
254{ 254{
255 int irq_mask = 0; 255 int irq_mask = 0;
256 256
257 if (!downlink) 257 if (!downlink)
258 return -EINVAL; 258 return -EINVAL;
259 259
260 /* Disable irq request generation */ 260 /* Disable irq request generation */
261 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; 261 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
262 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); 262 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
263 263
264 /* Disable DMA request generation */ 264 /* Disable DMA request generation */
265 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE); 265 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
266 266
267 /* clear Downlink channels */ 267 /* clear Downlink channels */
268 mcpdm->dn_channels = 0; 268 mcpdm->dn_channels = 0;
269 269
270 mcpdm->downlink = NULL; 270 mcpdm->downlink = NULL;
271 271
272 return 0; 272 return 0;
273} 273}
274 274
275static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id) 275static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
276{ 276{
277 struct omap_mcpdm *mcpdm_irq = dev_id; 277 struct omap_mcpdm *mcpdm_irq = dev_id;
278 int irq_status; 278 int irq_status;
279 279
280 irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS); 280 irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
281 281
282 /* Acknowledge irq event */ 282 /* Acknowledge irq event */
283 omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status); 283 omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
284 284
285 if (irq & MCPDM_DN_IRQ_FULL) { 285 if (irq & MCPDM_DN_IRQ_FULL) {
286 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); 286 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
287 omap_mcpdm_reset_playback(1); 287 omap_mcpdm_reset_playback(1);
288 omap_mcpdm_playback_open(mcpdm_irq->downlink); 288 omap_mcpdm_playback_open(mcpdm_irq->downlink);
289 omap_mcpdm_reset_playback(0); 289 omap_mcpdm_reset_playback(0);
290 } 290 }
291 291
292 if (irq & MCPDM_DN_IRQ_EMPTY) { 292 if (irq & MCPDM_DN_IRQ_EMPTY) {
293 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); 293 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
294 omap_mcpdm_reset_playback(1); 294 omap_mcpdm_reset_playback(1);
295 omap_mcpdm_playback_open(mcpdm_irq->downlink); 295 omap_mcpdm_playback_open(mcpdm_irq->downlink);
296 omap_mcpdm_reset_playback(0); 296 omap_mcpdm_reset_playback(0);
297 } 297 }
298 298
299 if (irq & MCPDM_DN_IRQ) { 299 if (irq & MCPDM_DN_IRQ) {
300 dev_dbg(mcpdm_irq->dev, "DN write request\n"); 300 dev_dbg(mcpdm_irq->dev, "DN write request\n");
301 } 301 }
302 302
303 if (irq & MCPDM_UP_IRQ_FULL) { 303 if (irq & MCPDM_UP_IRQ_FULL) {
304 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); 304 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
305 omap_mcpdm_reset_capture(1); 305 omap_mcpdm_reset_capture(1);
306 omap_mcpdm_capture_open(mcpdm_irq->uplink); 306 omap_mcpdm_capture_open(mcpdm_irq->uplink);
307 omap_mcpdm_reset_capture(0); 307 omap_mcpdm_reset_capture(0);
308 } 308 }
309 309
310 if (irq & MCPDM_UP_IRQ_EMPTY) { 310 if (irq & MCPDM_UP_IRQ_EMPTY) {
311 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); 311 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
312 omap_mcpdm_reset_capture(1); 312 omap_mcpdm_reset_capture(1);
313 omap_mcpdm_capture_open(mcpdm_irq->uplink); 313 omap_mcpdm_capture_open(mcpdm_irq->uplink);
314 omap_mcpdm_reset_capture(0); 314 omap_mcpdm_reset_capture(0);
315 } 315 }
316 316
317 if (irq & MCPDM_UP_IRQ) { 317 if (irq & MCPDM_UP_IRQ) {
318 dev_dbg(mcpdm_irq->dev, "UP write request\n"); 318 dev_dbg(mcpdm_irq->dev, "UP write request\n");
319 } 319 }
320 320
321 return IRQ_HANDLED; 321 return IRQ_HANDLED;
322} 322}
323 323
324int omap_mcpdm_request(void) 324int omap_mcpdm_request(void)
325{ 325{
326 int ret; 326 int ret;
327 327
328 clk_enable(mcpdm->clk); 328 clk_enable(mcpdm->clk);
329 329
330 spin_lock(&mcpdm->lock); 330 spin_lock(&mcpdm->lock);
331 331
332 if (!mcpdm->free) { 332 if (!mcpdm->free) {
333 dev_err(mcpdm->dev, "McPDM interface is in use\n"); 333 dev_err(mcpdm->dev, "McPDM interface is in use\n");
334 spin_unlock(&mcpdm->lock); 334 spin_unlock(&mcpdm->lock);
335 ret = -EBUSY; 335 ret = -EBUSY;
336 goto err; 336 goto err;
337 } 337 }
338 mcpdm->free = 0; 338 mcpdm->free = 0;
339 339
340 spin_unlock(&mcpdm->lock); 340 spin_unlock(&mcpdm->lock);
341 341
342 /* Disable lines while request is ongoing */ 342 /* Disable lines while request is ongoing */
343 omap_mcpdm_write(MCPDM_CTRL, 0x00); 343 omap_mcpdm_write(MCPDM_CTRL, 0x00);
344 344
345 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, 345 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
346 0, "McPDM", (void *)mcpdm); 346 0, "McPDM", (void *)mcpdm);
347 if (ret) { 347 if (ret) {
348 dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n"); 348 dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
349 goto err; 349 goto err;
350 } 350 }
351 351
352 return 0; 352 return 0;
353 353
354err: 354err:
355 clk_disable(mcpdm->clk); 355 clk_disable(mcpdm->clk);
356 return ret; 356 return ret;
357} 357}
358 358
359void omap_mcpdm_free(void) 359void omap_mcpdm_free(void)
360{ 360{
361 spin_lock(&mcpdm->lock); 361 spin_lock(&mcpdm->lock);
362 if (mcpdm->free) { 362 if (mcpdm->free) {
363 dev_err(mcpdm->dev, "McPDM interface is already free\n"); 363 dev_err(mcpdm->dev, "McPDM interface is already free\n");
364 spin_unlock(&mcpdm->lock); 364 spin_unlock(&mcpdm->lock);
365 return; 365 return;
366 } 366 }
367 mcpdm->free = 1; 367 mcpdm->free = 1;
368 spin_unlock(&mcpdm->lock); 368 spin_unlock(&mcpdm->lock);
369 369
370 clk_disable(mcpdm->clk); 370 clk_disable(mcpdm->clk);
371 371
372 free_irq(mcpdm->irq, (void *)mcpdm); 372 free_irq(mcpdm->irq, (void *)mcpdm);
373} 373}
374 374
375/* Enable/disable DC offset cancelation for the analog 375/* Enable/disable DC offset cancelation for the analog
@@ -377,108 +377,108 @@ void omap_mcpdm_free(void)
377 */ 377 */
378int omap_mcpdm_set_offset(int offset1, int offset2) 378int omap_mcpdm_set_offset(int offset1, int offset2)
379{ 379{
380 int offset; 380 int offset;
381 381
382 if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX)) 382 if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
383 return -EINVAL; 383 return -EINVAL;
384 384
385 offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2); 385 offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
386 386
387 /* offset cancellation for channel 1 */ 387 /* offset cancellation for channel 1 */
388 if (offset1) 388 if (offset1)
389 offset |= DN_OFST_RX1_EN; 389 offset |= DN_OFST_RX1_EN;
390 else 390 else
391 offset &= ~DN_OFST_RX1_EN; 391 offset &= ~DN_OFST_RX1_EN;
392 392
393 /* offset cancellation for channel 2 */ 393 /* offset cancellation for channel 2 */
394 if (offset2) 394 if (offset2)
395 offset |= DN_OFST_RX2_EN; 395 offset |= DN_OFST_RX2_EN;
396 else 396 else
397 offset &= ~DN_OFST_RX2_EN; 397 offset &= ~DN_OFST_RX2_EN;
398 398
399 omap_mcpdm_write(MCPDM_DN_OFFSET, offset); 399 omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
400 400
401 return 0; 401 return 0;
402} 402}
403 403
404static int __devinit omap_mcpdm_probe(struct platform_device *pdev) 404static int __devinit omap_mcpdm_probe(struct platform_device *pdev)
405{ 405{
406 struct resource *res; 406 struct resource *res;
407 int ret = 0; 407 int ret = 0;
408 408
409 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); 409 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
410 if (!mcpdm) { 410 if (!mcpdm) {
411 ret = -ENOMEM; 411 ret = -ENOMEM;
412 goto exit; 412 goto exit;
413 } 413 }
414 414
415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
416 if (res == NULL) { 416 if (res == NULL) {
417 dev_err(&pdev->dev, "no resource\n"); 417 dev_err(&pdev->dev, "no resource\n");
418 goto err_resource; 418 goto err_resource;
419 } 419 }
420 420
421 spin_lock_init(&mcpdm->lock); 421 spin_lock_init(&mcpdm->lock);
422 mcpdm->free = 1; 422 mcpdm->free = 1;
423 mcpdm->io_base = ioremap(res->start, resource_size(res)); 423 mcpdm->io_base = ioremap(res->start, resource_size(res));
424 if (!mcpdm->io_base) { 424 if (!mcpdm->io_base) {
425 ret = -ENOMEM; 425 ret = -ENOMEM;
426 goto err_resource; 426 goto err_resource;
427 } 427 }
428 428
429 mcpdm->irq = platform_get_irq(pdev, 0); 429 mcpdm->irq = platform_get_irq(pdev, 0);
430 430
431 mcpdm->clk = clk_get(&pdev->dev, "pdm_ck"); 431 mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
432 if (IS_ERR(mcpdm->clk)) { 432 if (IS_ERR(mcpdm->clk)) {
433 ret = PTR_ERR(mcpdm->clk); 433 ret = PTR_ERR(mcpdm->clk);
434 dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret); 434 dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
435 goto err_clk; 435 goto err_clk;
436 } 436 }
437 437
438 mcpdm->dev = &pdev->dev; 438 mcpdm->dev = &pdev->dev;
439 platform_set_drvdata(pdev, mcpdm); 439 platform_set_drvdata(pdev, mcpdm);
440 440
441 return 0; 441 return 0;
442 442
443err_clk: 443err_clk:
444 iounmap(mcpdm->io_base); 444 iounmap(mcpdm->io_base);
445err_resource: 445err_resource:
446 kfree(mcpdm); 446 kfree(mcpdm);
447exit: 447exit:
448 return ret; 448 return ret;
449} 449}
450 450
451static int __devexit omap_mcpdm_remove(struct platform_device *pdev) 451static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
452{ 452{
453 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); 453 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
454 454
455 platform_set_drvdata(pdev, NULL); 455 platform_set_drvdata(pdev, NULL);
456 456
457 clk_put(mcpdm_ptr->clk); 457 clk_put(mcpdm_ptr->clk);
458 458
459 iounmap(mcpdm_ptr->io_base); 459 iounmap(mcpdm_ptr->io_base);
460 460
461 mcpdm_ptr->clk = NULL; 461 mcpdm_ptr->clk = NULL;
462 mcpdm_ptr->free = 0; 462 mcpdm_ptr->free = 0;
463 mcpdm_ptr->dev = NULL; 463 mcpdm_ptr->dev = NULL;
464 464
465 kfree(mcpdm_ptr); 465 kfree(mcpdm_ptr);
466 466
467 return 0; 467 return 0;
468} 468}
469 469
470static struct platform_driver omap_mcpdm_driver = { 470static struct platform_driver omap_mcpdm_driver = {
471 .probe = omap_mcpdm_probe, 471 .probe = omap_mcpdm_probe,
472 .remove = __devexit_p(omap_mcpdm_remove), 472 .remove = __devexit_p(omap_mcpdm_remove),
473 .driver = { 473 .driver = {
474 .name = "omap-mcpdm", 474 .name = "omap-mcpdm",
475 }, 475 },
476}; 476};
477 477
478static struct platform_device *omap_mcpdm_device; 478static struct platform_device *omap_mcpdm_device;
479 479
480static int __init omap_mcpdm_init(void) 480static int __init omap_mcpdm_init(void)
481{ 481{
482 return platform_driver_register(&omap_mcpdm_driver); 482 return platform_driver_register(&omap_mcpdm_driver);
483} 483}
484arch_initcall(omap_mcpdm_init); 484arch_initcall(omap_mcpdm_init);
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index e814a9591f78..2d33a89f147a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -256,6 +256,31 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
256 return err; 256 return err;
257} 257}
258 258
259static snd_pcm_sframes_t omap_mcbsp_dai_delay(
260 struct snd_pcm_substream *substream,
261 struct snd_soc_dai *dai)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
265 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
266 u16 fifo_use;
267 snd_pcm_sframes_t delay;
268
269 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
270 fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
271 else
272 fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
273
274 /*
275 * Divide the used locations with the channel count to get the
276 * FIFO usage in samples (don't care about partial samples in the
277 * buffer).
278 */
279 delay = fifo_use / substream->runtime->channels;
280
281 return delay;
282}
283
259static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 284static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
260 struct snd_pcm_hw_params *params, 285 struct snd_pcm_hw_params *params,
261 struct snd_soc_dai *dai) 286 struct snd_soc_dai *dai)
@@ -297,7 +322,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
297 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; 322 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
298 omap_mcbsp_dai_dma_params[id][substream->stream].data_type = 323 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
299 OMAP_DMA_DATA_TYPE_S16; 324 OMAP_DMA_DATA_TYPE_S16;
300 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 325
326 snd_soc_dai_set_dma_data(cpu_dai, substream,
327 &omap_mcbsp_dai_dma_params[id][substream->stream]);
301 328
302 if (mcbsp_data->configured) { 329 if (mcbsp_data->configured) {
303 /* McBSP already configured by another stream */ 330 /* McBSP already configured by another stream */
@@ -306,7 +333,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
306 333
307 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; 334 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
308 wpf = channels = params_channels(params); 335 wpf = channels = params_channels(params);
309 if (channels == 2 && format == SND_SOC_DAIFMT_I2S) { 336 if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
337 format == SND_SOC_DAIFMT_LEFT_J)) {
310 /* Use dual-phase frames */ 338 /* Use dual-phase frames */
311 regs->rcr2 |= RPHASE; 339 regs->rcr2 |= RPHASE;
312 regs->xcr2 |= XPHASE; 340 regs->xcr2 |= XPHASE;
@@ -351,6 +379,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
351 /* Set FS period and length in terms of bit clock periods */ 379 /* Set FS period and length in terms of bit clock periods */
352 switch (format) { 380 switch (format) {
353 case SND_SOC_DAIFMT_I2S: 381 case SND_SOC_DAIFMT_I2S:
382 case SND_SOC_DAIFMT_LEFT_J:
354 regs->srgr2 |= FPER(framesize - 1); 383 regs->srgr2 |= FPER(framesize - 1);
355 regs->srgr1 |= FWID((framesize >> 1) - 1); 384 regs->srgr1 |= FWID((framesize >> 1) - 1);
356 break; 385 break;
@@ -402,6 +431,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
402 regs->rcr2 |= RDATDLY(1); 431 regs->rcr2 |= RDATDLY(1);
403 regs->xcr2 |= XDATDLY(1); 432 regs->xcr2 |= XDATDLY(1);
404 break; 433 break;
434 case SND_SOC_DAIFMT_LEFT_J:
435 /* 0-bit data delay */
436 regs->rcr2 |= RDATDLY(0);
437 regs->xcr2 |= XDATDLY(0);
438 regs->spcr1 |= RJUST(2);
439 /* Invert FS polarity configuration */
440 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
441 break;
405 case SND_SOC_DAIFMT_DSP_A: 442 case SND_SOC_DAIFMT_DSP_A:
406 /* 1-bit data delay */ 443 /* 1-bit data delay */
407 regs->rcr2 |= RDATDLY(1); 444 regs->rcr2 |= RDATDLY(1);
@@ -607,6 +644,7 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
607 .startup = omap_mcbsp_dai_startup, 644 .startup = omap_mcbsp_dai_startup,
608 .shutdown = omap_mcbsp_dai_shutdown, 645 .shutdown = omap_mcbsp_dai_shutdown,
609 .trigger = omap_mcbsp_dai_trigger, 646 .trigger = omap_mcbsp_dai_trigger,
647 .delay = omap_mcbsp_dai_delay,
610 .hw_params = omap_mcbsp_dai_hw_params, 648 .hw_params = omap_mcbsp_dai_hw_params,
611 .set_fmt = omap_mcbsp_dai_set_dai_fmt, 649 .set_fmt = omap_mcbsp_dai_set_dai_fmt,
612 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, 650 .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 25f19e4728bf..b7f4f7e015f3 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -150,7 +150,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
150 int stream = substream->stream; 150 int stream = substream->stream;
151 int channels, err, link_mask = 0; 151 int channels, err, link_mask = 0;
152 152
153 cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream]; 153 snd_soc_dai_set_dma_data(cpu_dai, substream,
154 &omap_mcpdm_dai_dma_params[stream]);
154 155
155 channels = params_channels(params); 156 channels = params_channels(params);
156 switch (channels) { 157 switch (channels) {
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 825db385f01f..39538c0f81f0 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -100,9 +100,11 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
100 struct snd_pcm_runtime *runtime = substream->runtime; 100 struct snd_pcm_runtime *runtime = substream->runtime;
101 struct snd_soc_pcm_runtime *rtd = substream->private_data; 101 struct snd_soc_pcm_runtime *rtd = substream->private_data;
102 struct omap_runtime_data *prtd = runtime->private_data; 102 struct omap_runtime_data *prtd = runtime->private_data;
103 struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data; 103 struct omap_pcm_dma_data *dma_data;
104 int err = 0; 104 int err = 0;
105 105
106 dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
107
106 /* return if this is a bufferless transfer e.g. 108 /* return if this is a bufferless transfer e.g.
107 * codec <--> BT codec or GSM modem -- lg FIXME */ 109 * codec <--> BT codec or GSM modem -- lg FIXME */
108 if (!dma_data) 110 if (!dma_data)
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 9e95e5117c88..6959c5199160 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -121,10 +121,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
121 ssp_disable(ssp); 121 ssp_disable(ssp);
122 } 122 }
123 123
124 if (cpu_dai->dma_data) { 124 kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
125 kfree(cpu_dai->dma_data); 125 snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
126 cpu_dai->dma_data = NULL; 126
127 }
128 return ret; 127 return ret;
129} 128}
130 129
@@ -141,10 +140,8 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
141 clk_disable(ssp->clk); 140 clk_disable(ssp->clk);
142 } 141 }
143 142
144 if (cpu_dai->dma_data) { 143 kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
145 kfree(cpu_dai->dma_data); 144 snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
146 cpu_dai->dma_data = NULL;
147 }
148} 145}
149 146
150#ifdef CONFIG_PM 147#ifdef CONFIG_PM
@@ -569,19 +566,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
569 u32 sspsp; 566 u32 sspsp;
570 int width = snd_pcm_format_physical_width(params_format(params)); 567 int width = snd_pcm_format_physical_width(params_format(params));
571 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; 568 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
569 struct pxa2xx_pcm_dma_params *dma_data;
570
571 dma_data = snd_soc_dai_get_dma_data(dai, substream);
572 572
573 /* generate correct DMA params */ 573 /* generate correct DMA params */
574 if (cpu_dai->dma_data) 574 kfree(dma_data);
575 kfree(cpu_dai->dma_data);
576 575
577 /* Network mode with one active slot (ttsa == 1) can be used 576 /* Network mode with one active slot (ttsa == 1) can be used
578 * to force 16-bit frame width on the wire (for S16_LE), even 577 * to force 16-bit frame width on the wire (for S16_LE), even
579 * with two channels. Use 16-bit DMA transfers for this case. 578 * with two channels. Use 16-bit DMA transfers for this case.
580 */ 579 */
581 cpu_dai->dma_data = ssp_get_dma_params(ssp, 580 dma_data = ssp_get_dma_params(ssp,
582 ((chn == 2) && (ttsa != 1)) || (width == 32), 581 ((chn == 2) && (ttsa != 1)) || (width == 32),
583 substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 582 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
584 583
584 snd_soc_dai_set_dma_data(dai, substream, dma_data);
585
585 /* we can only change the settings if the port is not in use */ 586 /* we can only change the settings if the port is not in use */
586 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 587 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
587 return 0; 588 return 0;
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index e9ae7b3a7e00..d314115e3dd7 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -122,11 +122,14 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
122{ 122{
123 struct snd_soc_pcm_runtime *rtd = substream->private_data; 123 struct snd_soc_pcm_runtime *rtd = substream->private_data;
124 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 124 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
125 struct pxa2xx_pcm_dma_params *dma_data;
125 126
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 127 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
127 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out; 128 dma_data = &pxa2xx_ac97_pcm_stereo_out;
128 else 129 else
129 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in; 130 dma_data = &pxa2xx_ac97_pcm_stereo_in;
131
132 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
130 133
131 return 0; 134 return 0;
132} 135}
@@ -137,11 +140,14 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
137{ 140{
138 struct snd_soc_pcm_runtime *rtd = substream->private_data; 141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
139 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 142 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
143 struct pxa2xx_pcm_dma_params *dma_data;
140 144
141 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
142 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out; 146 dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
143 else 147 else
144 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in; 148 dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
149
150 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
145 151
146 return 0; 152 return 0;
147} 153}
@@ -156,7 +162,8 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
156 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 162 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
157 return -ENODEV; 163 return -ENODEV;
158 else 164 else
159 cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in; 165 snd_soc_dai_set_dma_data(cpu_dai, substream,
166 &pxa2xx_ac97_pcm_mic_mono_in);
160 167
161 return 0; 168 return 0;
162} 169}
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 6b8f655d1ad8..c1a5275721e4 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -164,6 +164,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
164{ 164{
165 struct snd_soc_pcm_runtime *rtd = substream->private_data; 165 struct snd_soc_pcm_runtime *rtd = substream->private_data;
166 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 166 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
167 struct pxa2xx_pcm_dma_params *dma_data;
167 168
168 BUG_ON(IS_ERR(clk_i2s)); 169 BUG_ON(IS_ERR(clk_i2s));
169 clk_enable(clk_i2s); 170 clk_enable(clk_i2s);
@@ -171,9 +172,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
171 pxa_i2s_wait(); 172 pxa_i2s_wait();
172 173
173 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
174 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out; 175 dma_data = &pxa2xx_i2s_pcm_stereo_out;
175 else 176 else
176 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in; 177 dma_data = &pxa2xx_i2s_pcm_stereo_in;
178
179 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
177 180
178 /* is port used by another stream */ 181 /* is port used by another stream */
179 if (!(SACR0 & SACR0_ENB)) { 182 if (!(SACR0 & SACR0_ENB)) {
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index d38e39575f51..adc7e6f15f93 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -25,9 +25,11 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
25 struct snd_pcm_runtime *runtime = substream->runtime; 25 struct snd_pcm_runtime *runtime = substream->runtime;
26 struct pxa2xx_runtime_data *prtd = runtime->private_data; 26 struct pxa2xx_runtime_data *prtd = runtime->private_data;
27 struct snd_soc_pcm_runtime *rtd = substream->private_data; 27 struct snd_soc_pcm_runtime *rtd = substream->private_data;
28 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; 28 struct pxa2xx_pcm_dma_params *dma;
29 int ret; 29 int ret;
30 30
31 dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
32
31 /* return if this is a bufferless transfer e.g. 33 /* return if this is a bufferless transfer e.g.
32 * codec <--> BT codec or GSM modem -- lg FIXME */ 34 * codec <--> BT codec or GSM modem -- lg FIXME */
33 if (!dma) 35 if (!dma)
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c
index ee8ed9d7e703..ecf4fd04ae96 100644
--- a/sound/soc/s3c24xx/s3c-ac97.c
+++ b/sound/soc/s3c24xx/s3c-ac97.c
@@ -224,11 +224,14 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
224{ 224{
225 struct snd_soc_pcm_runtime *rtd = substream->private_data; 225 struct snd_soc_pcm_runtime *rtd = substream->private_data;
226 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 226 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
227 struct s3c_dma_params *dma_data;
227 228
228 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 229 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
229 cpu_dai->dma_data = &s3c_ac97_pcm_out; 230 dma_data = &s3c_ac97_pcm_out;
230 else 231 else
231 cpu_dai->dma_data = &s3c_ac97_pcm_in; 232 dma_data = &s3c_ac97_pcm_in;
233
234 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
232 235
233 return 0; 236 return 0;
234} 237}
@@ -238,8 +241,8 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
238{ 241{
239 u32 ac_glbctrl; 242 u32 ac_glbctrl;
240 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct snd_soc_pcm_runtime *rtd = substream->private_data;
241 int channel = ((struct s3c_dma_params *) 244 struct s3c_dma_params *dma_data =
242 rtd->dai->cpu_dai->dma_data)->channel; 245 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
243 246
244 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); 247 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
245 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 248 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -265,7 +268,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
265 268
266 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 269 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
267 270
268 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); 271 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
269 272
270 return 0; 273 return 0;
271} 274}
@@ -280,7 +283,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
280 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 283 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
281 return -ENODEV; 284 return -ENODEV;
282 else 285 else
283 cpu_dai->dma_data = &s3c_ac97_mic_in; 286 snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
284 287
285 return 0; 288 return 0;
286} 289}
@@ -290,8 +293,8 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
290{ 293{
291 u32 ac_glbctrl; 294 u32 ac_glbctrl;
292 struct snd_soc_pcm_runtime *rtd = substream->private_data; 295 struct snd_soc_pcm_runtime *rtd = substream->private_data;
293 int channel = ((struct s3c_dma_params *) 296 struct s3c_dma_params *dma_data =
294 rtd->dai->cpu_dai->dma_data)->channel; 297 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
295 298
296 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); 299 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
297 ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; 300 ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
@@ -311,7 +314,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
311 314
312 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 315 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
313 316
314 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); 317 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
315 318
316 return 0; 319 return 0;
317} 320}
diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c
index 7725e26d6c91..1b61c23ff300 100644
--- a/sound/soc/s3c24xx/s3c-dma.c
+++ b/sound/soc/s3c24xx/s3c-dma.c
@@ -145,10 +145,12 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
145 struct snd_pcm_runtime *runtime = substream->runtime; 145 struct snd_pcm_runtime *runtime = substream->runtime;
146 struct s3c24xx_runtime_data *prtd = runtime->private_data; 146 struct s3c24xx_runtime_data *prtd = runtime->private_data;
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data;
149 unsigned long totbytes = params_buffer_bytes(params); 148 unsigned long totbytes = params_buffer_bytes(params);
149 struct s3c_dma_params *dma =
150 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
150 int ret = 0; 151 int ret = 0;
151 152
153
152 pr_debug("Entered %s\n", __func__); 154 pr_debug("Entered %s\n", __func__);
153 155
154 /* return if this is a bufferless transfer e.g. 156 /* return if this is a bufferless transfer e.g.
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index e994d8374fe6..865f93143bf1 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -16,18 +16,12 @@
16 * option) any later version. 16 * option) any later version.
17 */ 17 */
18 18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/delay.h> 19#include <linux/delay.h>
23#include <linux/clk.h> 20#include <linux/clk.h>
24#include <linux/kernel.h>
25#include <linux/io.h> 21#include <linux/io.h>
26 22
27#include <sound/core.h>
28#include <sound/pcm.h> 23#include <sound/pcm.h>
29#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
30#include <sound/initval.h>
31#include <sound/soc.h> 25#include <sound/soc.h>
32 26
33#include <plat/regs-s3c2412-iis.h> 27#include <plat/regs-s3c2412-iis.h>
@@ -332,54 +326,41 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
332 return 0; 326 return 0;
333} 327}
334 328
335static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, 329static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
336 struct snd_pcm_hw_params *params, 330 struct snd_pcm_hw_params *params,
337 struct snd_soc_dai *socdai) 331 struct snd_soc_dai *socdai)
338{ 332{
339 struct snd_soc_pcm_runtime *rtd = substream->private_data; 333 struct snd_soc_pcm_runtime *rtd = substream->private_data;
340 struct snd_soc_dai_link *dai = rtd->dai; 334 struct snd_soc_dai_link *dai = rtd->dai;
341 struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); 335 struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
336 struct s3c_dma_params *dma_data;
342 u32 iismod; 337 u32 iismod;
343 338
344 pr_debug("Entered %s\n", __func__); 339 pr_debug("Entered %s\n", __func__);
345 340
346 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 341 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
347 dai->cpu_dai->dma_data = i2s->dma_playback; 342 dma_data = i2s->dma_playback;
348 else 343 else
349 dai->cpu_dai->dma_data = i2s->dma_capture; 344 dma_data = i2s->dma_capture;
345
346 snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
350 347
351 /* Working copies of register */ 348 /* Working copies of register */
352 iismod = readl(i2s->regs + S3C2412_IISMOD); 349 iismod = readl(i2s->regs + S3C2412_IISMOD);
353 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); 350 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
354 351
355#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) 352 iismod &= ~S3C64XX_IISMOD_BLC_MASK;
356 switch (params_format(params)) {
357 case SNDRV_PCM_FORMAT_S8:
358 iismod |= S3C2412_IISMOD_8BIT;
359 break;
360 case SNDRV_PCM_FORMAT_S16_LE:
361 iismod &= ~S3C2412_IISMOD_8BIT;
362 break;
363 }
364#endif
365
366#ifdef CONFIG_PLAT_S3C64XX
367 iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
368 /* Sample size */ 353 /* Sample size */
369 switch (params_format(params)) { 354 switch (params_format(params)) {
370 case SNDRV_PCM_FORMAT_S8: 355 case SNDRV_PCM_FORMAT_S8:
371 /* 8 bit sample, 16fs BCLK */ 356 iismod |= S3C64XX_IISMOD_BLC_8BIT;
372 iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
373 break; 357 break;
374 case SNDRV_PCM_FORMAT_S16_LE: 358 case SNDRV_PCM_FORMAT_S16_LE:
375 /* 16 bit sample, 32fs BCLK */
376 break; 359 break;
377 case SNDRV_PCM_FORMAT_S24_LE: 360 case SNDRV_PCM_FORMAT_S24_LE:
378 /* 24 bit sample, 48fs BCLK */ 361 iismod |= S3C64XX_IISMOD_BLC_24BIT;
379 iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
380 break; 362 break;
381 } 363 }
382#endif
383 364
384 writel(iismod, i2s->regs + S3C2412_IISMOD); 365 writel(iismod, i2s->regs + S3C2412_IISMOD);
385 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); 366 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
@@ -394,8 +375,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
394 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 375 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
395 unsigned long irqs; 376 unsigned long irqs;
396 int ret = 0; 377 int ret = 0;
397 int channel = ((struct s3c_dma_params *) 378 struct s3c_dma_params *dma_data =
398 rtd->dai->cpu_dai->dma_data)->channel; 379 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
399 380
400 pr_debug("Entered %s\n", __func__); 381 pr_debug("Entered %s\n", __func__);
401 382
@@ -431,7 +412,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
431 * of the auto reload mechanism of S3C24XX. 412 * of the auto reload mechanism of S3C24XX.
432 * This call won't bother S3C64XX. 413 * This call won't bother S3C64XX.
433 */ 414 */
434 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); 415 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
435 416
436 break; 417 break;
437 418
@@ -469,29 +450,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
469 450
470 switch (div_id) { 451 switch (div_id) {
471 case S3C_I2SV2_DIV_BCLK: 452 case S3C_I2SV2_DIV_BCLK:
472 if (div > 3) { 453 switch (div) {
473 /* convert value to bit field */ 454 case 16:
474 455 div = S3C2412_IISMOD_BCLK_16FS;
475 switch (div) { 456 break;
476 case 16:
477 div = S3C2412_IISMOD_BCLK_16FS;
478 break;
479 457
480 case 32: 458 case 32:
481 div = S3C2412_IISMOD_BCLK_32FS; 459 div = S3C2412_IISMOD_BCLK_32FS;
482 break; 460 break;
483 461
484 case 24: 462 case 24:
485 div = S3C2412_IISMOD_BCLK_24FS; 463 div = S3C2412_IISMOD_BCLK_24FS;
486 break; 464 break;
487 465
488 case 48: 466 case 48:
489 div = S3C2412_IISMOD_BCLK_48FS; 467 div = S3C2412_IISMOD_BCLK_48FS;
490 break; 468 break;
491 469
492 default: 470 default:
493 return -EINVAL; 471 return -EINVAL;
494 }
495 } 472 }
496 473
497 reg = readl(i2s->regs + S3C2412_IISMOD); 474 reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -502,29 +479,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
502 break; 479 break;
503 480
504 case S3C_I2SV2_DIV_RCLK: 481 case S3C_I2SV2_DIV_RCLK:
505 if (div > 3) { 482 switch (div) {
506 /* convert value to bit field */ 483 case 256:
507 484 div = S3C2412_IISMOD_RCLK_256FS;
508 switch (div) { 485 break;
509 case 256:
510 div = S3C2412_IISMOD_RCLK_256FS;
511 break;
512 486
513 case 384: 487 case 384:
514 div = S3C2412_IISMOD_RCLK_384FS; 488 div = S3C2412_IISMOD_RCLK_384FS;
515 break; 489 break;
516 490
517 case 512: 491 case 512:
518 div = S3C2412_IISMOD_RCLK_512FS; 492 div = S3C2412_IISMOD_RCLK_512FS;
519 break; 493 break;
520 494
521 case 768: 495 case 768:
522 div = S3C2412_IISMOD_RCLK_768FS; 496 div = S3C2412_IISMOD_RCLK_768FS;
523 break; 497 break;
524 498
525 default: 499 default:
526 return -EINVAL; 500 return -EINVAL;
527 }
528 } 501 }
529 502
530 reg = readl(i2s->regs + S3C2412_IISMOD); 503 reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -550,6 +523,21 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
550 return 0; 523 return 0;
551} 524}
552 525
526static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream,
527 struct snd_soc_dai *dai)
528{
529 struct s3c_i2sv2_info *i2s = to_info(dai);
530 u32 reg = readl(i2s->regs + S3C2412_IISFIC);
531 snd_pcm_sframes_t delay;
532
533 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
534 delay = S3C2412_IISFIC_TXCOUNT(reg);
535 else
536 delay = S3C2412_IISFIC_RXCOUNT(reg);
537
538 return delay;
539}
540
553/* default table of all avaialable root fs divisors */ 541/* default table of all avaialable root fs divisors */
554static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; 542static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
555 543
@@ -732,10 +720,15 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
732 struct snd_soc_dai_ops *ops = dai->ops; 720 struct snd_soc_dai_ops *ops = dai->ops;
733 721
734 ops->trigger = s3c2412_i2s_trigger; 722 ops->trigger = s3c2412_i2s_trigger;
735 ops->hw_params = s3c2412_i2s_hw_params; 723 if (!ops->hw_params)
724 ops->hw_params = s3c_i2sv2_hw_params;
736 ops->set_fmt = s3c2412_i2s_set_fmt; 725 ops->set_fmt = s3c2412_i2s_set_fmt;
737 ops->set_clkdiv = s3c2412_i2s_set_clkdiv; 726 ops->set_clkdiv = s3c2412_i2s_set_clkdiv;
738 727
728 /* Allow overriding by (for example) IISv4 */
729 if (!ops->delay)
730 ops->delay = s3c2412_i2s_delay;
731
739 dai->suspend = s3c2412_i2s_suspend; 732 dai->suspend = s3c2412_i2s_suspend;
740 dai->resume = s3c2412_i2s_resume; 733 dai->resume = s3c2412_i2s_resume;
741 734
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
index ecf8eaaed1db..b094d3c23cbe 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -25,6 +25,10 @@
25#define S3C_I2SV2_DIV_RCLK (2) 25#define S3C_I2SV2_DIV_RCLK (2)
26#define S3C_I2SV2_DIV_PRESCALER (3) 26#define S3C_I2SV2_DIV_PRESCALER (3)
27 27
28#define S3C_I2SV2_CLKSRC_PCLK 0
29#define S3C_I2SV2_CLKSRC_AUDIOBUS 1
30#define S3C_I2SV2_CLKSRC_CDCLK 2
31
28/** 32/**
29 * struct s3c_i2sv2_info - S3C I2S-V2 information 33 * struct s3c_i2sv2_info - S3C I2S-V2 information
30 * @dev: The parent device passed to use from the probe. 34 * @dev: The parent device passed to use from the probe.
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c
index a98f40c3cd29..326f0a9e7e30 100644
--- a/sound/soc/s3c24xx/s3c-pcm.c
+++ b/sound/soc/s3c24xx/s3c-pcm.c
@@ -178,6 +178,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
178 struct snd_soc_pcm_runtime *rtd = substream->private_data; 178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai_link *dai = rtd->dai; 179 struct snd_soc_dai_link *dai = rtd->dai;
180 struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); 180 struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
181 struct s3c_dma_params *dma_data;
181 void __iomem *regs = pcm->regs; 182 void __iomem *regs = pcm->regs;
182 struct clk *clk; 183 struct clk *clk;
183 int sclk_div, sync_div; 184 int sclk_div, sync_div;
@@ -187,9 +188,11 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
187 dev_dbg(pcm->dev, "Entered %s\n", __func__); 188 dev_dbg(pcm->dev, "Entered %s\n", __func__);
188 189
189 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 190 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
190 dai->cpu_dai->dma_data = pcm->dma_playback; 191 dma_data = pcm->dma_playback;
191 else 192 else
192 dai->cpu_dai->dma_data = pcm->dma_capture; 193 dma_data = pcm->dma_capture;
194
195 snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
193 196
194 /* Strictly check for sample size */ 197 /* Strictly check for sample size */
195 switch (params_format(params)) { 198 switch (params_format(params)) {
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index 359e59346ba2..f3148f98b419 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -103,6 +103,10 @@ struct clk *s3c2412_get_iisclk(void)
103} 103}
104EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); 104EXPORT_SYMBOL_GPL(s3c2412_get_iisclk);
105 105
106static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
107{
108 return cpu_dai->private_data;
109}
106 110
107static int s3c2412_i2s_probe(struct platform_device *pdev, 111static int s3c2412_i2s_probe(struct platform_device *pdev,
108 struct snd_soc_dai *dai) 112 struct snd_soc_dai *dai)
@@ -142,6 +146,41 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
142 return 0; 146 return 0;
143} 147}
144 148
149static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
150 struct snd_pcm_hw_params *params,
151 struct snd_soc_dai *cpu_dai)
152{
153 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
154 struct s3c_dma_params *dma_data;
155 u32 iismod;
156
157 pr_debug("Entered %s\n", __func__);
158
159 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
160 dma_data = i2s->dma_playback;
161 else
162 dma_data = i2s->dma_capture;
163
164 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
165
166 iismod = readl(i2s->regs + S3C2412_IISMOD);
167 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
168
169 switch (params_format(params)) {
170 case SNDRV_PCM_FORMAT_S8:
171 iismod |= S3C2412_IISMOD_8BIT;
172 break;
173 case SNDRV_PCM_FORMAT_S16_LE:
174 iismod &= ~S3C2412_IISMOD_8BIT;
175 break;
176 }
177
178 writel(iismod, i2s->regs + S3C2412_IISMOD);
179 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
180
181 return 0;
182}
183
145#define S3C2412_I2S_RATES \ 184#define S3C2412_I2S_RATES \
146 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ 185 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
147 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 186 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
@@ -149,6 +188,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
149 188
150static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { 189static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
151 .set_sysclk = s3c2412_i2s_set_sysclk, 190 .set_sysclk = s3c2412_i2s_set_sysclk,
191 .hw_params = s3c2412_i2s_hw_params,
152}; 192};
153 193
154struct snd_soc_dai s3c2412_i2s_dai = { 194struct snd_soc_dai s3c2412_i2s_dai = {
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
index 92848e54be16..60cac002a830 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ b/sound/soc/s3c24xx/s3c2412-i2s.h
@@ -21,8 +21,8 @@
21#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK 21#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK
22#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER 22#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
23 23
24#define S3C2412_CLKSRC_PCLK (0) 24#define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
25#define S3C2412_CLKSRC_I2SCLK (1) 25#define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS
26 26
27extern struct clk *s3c2412_get_iisclk(void); 27extern struct clk *s3c2412_get_iisclk(void);
28 28
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 0bc5950b9f02..c3ac890a3986 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -242,14 +242,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
242 struct snd_soc_dai *dai) 242 struct snd_soc_dai *dai)
243{ 243{
244 struct snd_soc_pcm_runtime *rtd = substream->private_data; 244 struct snd_soc_pcm_runtime *rtd = substream->private_data;
245 struct s3c_dma_params *dma_data;
245 u32 iismod; 246 u32 iismod;
246 247
247 pr_debug("Entered %s\n", __func__); 248 pr_debug("Entered %s\n", __func__);
248 249
249 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 250 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
250 rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; 251 dma_data = &s3c24xx_i2s_pcm_stereo_out;
251 else 252 else
252 rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in; 253 dma_data = &s3c24xx_i2s_pcm_stereo_in;
254
255 snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data);
253 256
254 /* Working copies of register */ 257 /* Working copies of register */
255 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); 258 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -258,13 +261,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
258 switch (params_format(params)) { 261 switch (params_format(params)) {
259 case SNDRV_PCM_FORMAT_S8: 262 case SNDRV_PCM_FORMAT_S8:
260 iismod &= ~S3C2410_IISMOD_16BIT; 263 iismod &= ~S3C2410_IISMOD_16BIT;
261 ((struct s3c_dma_params *) 264 dma_data->dma_size = 1;
262 rtd->dai->cpu_dai->dma_data)->dma_size = 1;
263 break; 265 break;
264 case SNDRV_PCM_FORMAT_S16_LE: 266 case SNDRV_PCM_FORMAT_S16_LE:
265 iismod |= S3C2410_IISMOD_16BIT; 267 iismod |= S3C2410_IISMOD_16BIT;
266 ((struct s3c_dma_params *) 268 dma_data->dma_size = 2;
267 rtd->dai->cpu_dai->dma_data)->dma_size = 2;
268 break; 269 break;
269 default: 270 default:
270 return -EINVAL; 271 return -EINVAL;
@@ -280,8 +281,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
280{ 281{
281 int ret = 0; 282 int ret = 0;
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 int channel = ((struct s3c_dma_params *) 284 struct s3c_dma_params *dma_data =
284 rtd->dai->cpu_dai->dma_data)->channel; 285 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
285 286
286 pr_debug("Entered %s\n", __func__); 287 pr_debug("Entered %s\n", __func__);
287 288
@@ -300,7 +301,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
300 else 301 else
301 s3c24xx_snd_txctrl(1); 302 s3c24xx_snd_txctrl(1);
302 303
303 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); 304 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
304 break; 305 break;
305 case SNDRV_PCM_TRIGGER_STOP: 306 case SNDRV_PCM_TRIGGER_STOP:
306 case SNDRV_PCM_TRIGGER_SUSPEND: 307 case SNDRV_PCM_TRIGGER_SUSPEND:
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index a72c251401ac..ab1fa159d3ae 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -12,9 +12,6 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/device.h>
18#include <linux/clk.h> 15#include <linux/clk.h>
19#include <linux/gpio.h> 16#include <linux/gpio.h>
20#include <linux/io.h> 17#include <linux/io.h>
@@ -130,15 +127,6 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev,
130} 127}
131 128
132 129
133#define S3C64XX_I2S_RATES \
134 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
135 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
136 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
137
138#define S3C64XX_I2S_FMTS \
139 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
140 SNDRV_PCM_FMTBIT_S24_LE)
141
142static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { 130static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = {
143 .set_sysclk = s3c64xx_i2s_set_sysclk, 131 .set_sysclk = s3c64xx_i2s_set_sysclk,
144}; 132};
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index abe7253b55fc..53d2a0a0df36 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -23,9 +23,18 @@ struct clk;
23#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK 23#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
24#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER 24#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
25 25
26#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
27#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX S3C_I2SV2_CLKSRC_AUDIOBUS
28#define S3C64XX_CLKSRC_CDCLK (2) 28#define S3C64XX_CLKSRC_CDCLK S3C_I2SV2_CLKSRC_CDCLK
29
30#define S3C64XX_I2S_RATES \
31 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
32 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
33 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
34
35#define S3C64XX_I2S_FMTS \
36 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
37 SNDRV_PCM_FMTBIT_S24_LE)
29 38
30extern struct snd_soc_dai s3c64xx_i2s_dai[]; 39extern struct snd_soc_dai s3c64xx_i2s_dai[];
31 40
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index c5cda187ecab..fa23854c5f3a 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -518,7 +518,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
518 518
519 s6000_i2s_dai.dev = &pdev->dev; 519 s6000_i2s_dai.dev = &pdev->dev;
520 s6000_i2s_dai.private_data = dev; 520 s6000_i2s_dai.private_data = dev;
521 s6000_i2s_dai.dma_data = &dev->dma_params; 521 s6000_i2s_dai.capture.dma_data = &dev->dma_params;
522 s6000_i2s_dai.playback.dma_data = &dev->dma_params;
522 523
523 dev->sifbase = sifmem->start; 524 dev->sifbase = sifmem->start;
524 dev->scbbase = mmio; 525 dev->scbbase = mmio;
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 1d61109e09fa..9c7f7f00cebb 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -58,13 +58,15 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
58 struct snd_pcm_runtime *runtime = substream->runtime; 58 struct snd_pcm_runtime *runtime = substream->runtime;
59 struct s6000_runtime_data *prtd = runtime->private_data; 59 struct s6000_runtime_data *prtd = runtime->private_data;
60 struct snd_soc_pcm_runtime *soc_runtime = substream->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; 61 struct s6000_pcm_dma_params *par;
62 int channel; 62 int channel;
63 unsigned int period_size; 63 unsigned int period_size;
64 unsigned int dma_offset; 64 unsigned int dma_offset;
65 dma_addr_t dma_pos; 65 dma_addr_t dma_pos;
66 dma_addr_t src, dst; 66 dma_addr_t src, dst;
67 67
68 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
69
68 period_size = snd_pcm_lib_period_bytes(substream); 70 period_size = snd_pcm_lib_period_bytes(substream);
69 dma_offset = prtd->period * period_size; 71 dma_offset = prtd->period * period_size;
70 dma_pos = runtime->dma_addr + dma_offset; 72 dma_pos = runtime->dma_addr + dma_offset;
@@ -101,7 +103,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
101{ 103{
102 struct snd_pcm *pcm = data; 104 struct snd_pcm *pcm = data;
103 struct snd_soc_pcm_runtime *runtime = pcm->private_data; 105 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
104 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; 106 struct s6000_pcm_dma_params *params =
107 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
105 struct s6000_runtime_data *prtd; 108 struct s6000_runtime_data *prtd;
106 unsigned int has_xrun; 109 unsigned int has_xrun;
107 int i, ret = IRQ_NONE; 110 int i, ret = IRQ_NONE;
@@ -172,11 +175,13 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream)
172{ 175{
173 struct s6000_runtime_data *prtd = substream->runtime->private_data; 176 struct s6000_runtime_data *prtd = substream->runtime->private_data;
174 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 177 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
175 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 178 struct s6000_pcm_dma_params *par;
176 unsigned long flags; 179 unsigned long flags;
177 int srcinc; 180 int srcinc;
178 u32 dma; 181 u32 dma;
179 182
183 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
184
180 spin_lock_irqsave(&prtd->lock, flags); 185 spin_lock_irqsave(&prtd->lock, flags);
181 186
182 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -212,10 +217,12 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
212{ 217{
213 struct s6000_runtime_data *prtd = substream->runtime->private_data; 218 struct s6000_runtime_data *prtd = substream->runtime->private_data;
214 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 219 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
215 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 220 struct s6000_pcm_dma_params *par;
216 unsigned long flags; 221 unsigned long flags;
217 u32 channel; 222 u32 channel;
218 223
224 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
225
219 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
220 channel = par->dma_out; 227 channel = par->dma_out;
221 else 228 else
@@ -236,9 +243,11 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
236static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 243static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
237{ 244{
238 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 245 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
239 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 246 struct s6000_pcm_dma_params *par;
240 int ret; 247 int ret;
241 248
249 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
250
242 ret = par->trigger(substream, cmd, 0); 251 ret = par->trigger(substream, cmd, 0);
243 if (ret < 0) 252 if (ret < 0)
244 return ret; 253 return ret;
@@ -275,13 +284,15 @@ static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
275static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) 284static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
276{ 285{
277 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 286 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
278 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 287 struct s6000_pcm_dma_params *par;
279 struct snd_pcm_runtime *runtime = substream->runtime; 288 struct snd_pcm_runtime *runtime = substream->runtime;
280 struct s6000_runtime_data *prtd = runtime->private_data; 289 struct s6000_runtime_data *prtd = runtime->private_data;
281 unsigned long flags; 290 unsigned long flags;
282 unsigned int offset; 291 unsigned int offset;
283 dma_addr_t count; 292 dma_addr_t count;
284 293
294 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
295
285 spin_lock_irqsave(&prtd->lock, flags); 296 spin_lock_irqsave(&prtd->lock, flags);
286 297
287 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 298 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -305,11 +316,12 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
305static int s6000_pcm_open(struct snd_pcm_substream *substream) 316static int s6000_pcm_open(struct snd_pcm_substream *substream)
306{ 317{
307 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 318 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
308 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 319 struct s6000_pcm_dma_params *par;
309 struct snd_pcm_runtime *runtime = substream->runtime; 320 struct snd_pcm_runtime *runtime = substream->runtime;
310 struct s6000_runtime_data *prtd; 321 struct s6000_runtime_data *prtd;
311 int ret; 322 int ret;
312 323
324 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
313 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); 325 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
314 326
315 ret = snd_pcm_hw_constraint_step(runtime, 0, 327 ret = snd_pcm_hw_constraint_step(runtime, 0,
@@ -364,7 +376,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
364 struct snd_pcm_hw_params *hw_params) 376 struct snd_pcm_hw_params *hw_params)
365{ 377{
366 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 378 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
367 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 379 struct s6000_pcm_dma_params *par;
368 int ret; 380 int ret;
369 ret = snd_pcm_lib_malloc_pages(substream, 381 ret = snd_pcm_lib_malloc_pages(substream,
370 params_buffer_bytes(hw_params)); 382 params_buffer_bytes(hw_params));
@@ -373,6 +385,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
373 return ret; 385 return ret;
374 } 386 }
375 387
388 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
389
376 if (par->same_rate) { 390 if (par->same_rate) {
377 spin_lock(&par->lock); 391 spin_lock(&par->lock);
378 if (par->rate == -1 || 392 if (par->rate == -1 ||
@@ -392,7 +406,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
392static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) 406static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
393{ 407{
394 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 408 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
395 struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; 409 struct s6000_pcm_dma_params *par =
410 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
396 411
397 spin_lock(&par->lock); 412 spin_lock(&par->lock);
398 par->in_use &= ~(1 << substream->stream); 413 par->in_use &= ~(1 << substream->stream);
@@ -417,7 +432,8 @@ static struct snd_pcm_ops s6000_pcm_ops = {
417static void s6000_pcm_free(struct snd_pcm *pcm) 432static void s6000_pcm_free(struct snd_pcm *pcm)
418{ 433{
419 struct snd_soc_pcm_runtime *runtime = pcm->private_data; 434 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
420 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; 435 struct s6000_pcm_dma_params *params =
436 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
421 437
422 free_irq(params->irq, pcm); 438 free_irq(params->irq, pcm);
423 snd_pcm_lib_preallocate_free_for_all(pcm); 439 snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -429,9 +445,11 @@ static int s6000_pcm_new(struct snd_card *card,
429 struct snd_soc_dai *dai, struct snd_pcm *pcm) 445 struct snd_soc_dai *dai, struct snd_pcm *pcm)
430{ 446{
431 struct snd_soc_pcm_runtime *runtime = pcm->private_data; 447 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
432 struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; 448 struct s6000_pcm_dma_params *params;
433 int res; 449 int res;
434 450
451 params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
452
435 if (!card->dev->dma_mask) 453 if (!card->dev->dma_mask)
436 card->dev->dma_mask = &s6000_pcm_dmamask; 454 card->dev->dma_mask = &s6000_pcm_dmamask;
437 if (!card->dev->coherent_dma_mask) 455 if (!card->dev->coherent_dma_mask)
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 5869dc3be781..9dfe9a58a314 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -159,7 +159,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
159 159
160 BUG_ON(codec->volatile_register); 160 BUG_ON(codec->volatile_register);
161 161
162 data[0] = reg & 0xff; 162 reg &= 0xff;
163 data[0] = reg;
163 data[1] = value & 0xff; 164 data[1] = value & 0xff;
164 165
165 if (reg < codec->reg_cache_size) 166 if (reg < codec->reg_cache_size)
@@ -180,6 +181,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
180 unsigned int reg) 181 unsigned int reg)
181{ 182{
182 u8 *cache = codec->reg_cache; 183 u8 *cache = codec->reg_cache;
184 reg &= 0xff;
183 if (reg >= codec->reg_cache_size) 185 if (reg >= codec->reg_cache_size)
184 return -1; 186 return -1;
185 return cache[reg]; 187 return cache[reg];
@@ -226,6 +228,40 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
226} 228}
227 229
228#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) 230#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
231static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
232 unsigned int r)
233{
234 struct i2c_msg xfer[2];
235 u8 reg = r;
236 u8 data;
237 int ret;
238 struct i2c_client *client = codec->control_data;
239
240 /* Write register */
241 xfer[0].addr = client->addr;
242 xfer[0].flags = 0;
243 xfer[0].len = 1;
244 xfer[0].buf = &reg;
245
246 /* Read data */
247 xfer[1].addr = client->addr;
248 xfer[1].flags = I2C_M_RD;
249 xfer[1].len = 1;
250 xfer[1].buf = &data;
251
252 ret = i2c_transfer(client->adapter, xfer, 2);
253 if (ret != 2) {
254 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
255 return 0;
256 }
257
258 return data;
259}
260#else
261#define snd_soc_8_8_read_i2c NULL
262#endif
263
264#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
229static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, 265static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
230 unsigned int r) 266 unsigned int r)
231{ 267{
@@ -366,6 +402,84 @@ static int snd_soc_16_8_spi_write(void *control_data, const char *data,
366#define snd_soc_16_8_spi_write NULL 402#define snd_soc_16_8_spi_write NULL
367#endif 403#endif
368 404
405#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
406static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
407 unsigned int r)
408{
409 struct i2c_msg xfer[2];
410 u16 reg = cpu_to_be16(r);
411 u16 data;
412 int ret;
413 struct i2c_client *client = codec->control_data;
414
415 /* Write register */
416 xfer[0].addr = client->addr;
417 xfer[0].flags = 0;
418 xfer[0].len = 2;
419 xfer[0].buf = (u8 *)&reg;
420
421 /* Read data */
422 xfer[1].addr = client->addr;
423 xfer[1].flags = I2C_M_RD;
424 xfer[1].len = 2;
425 xfer[1].buf = (u8 *)&data;
426
427 ret = i2c_transfer(client->adapter, xfer, 2);
428 if (ret != 2) {
429 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
430 return 0;
431 }
432
433 return be16_to_cpu(data);
434}
435#else
436#define snd_soc_16_16_read_i2c NULL
437#endif
438
439static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
440 unsigned int reg)
441{
442 u16 *cache = codec->reg_cache;
443
444 if (reg >= codec->reg_cache_size ||
445 snd_soc_codec_volatile_register(codec, reg)) {
446 if (codec->cache_only)
447 return -EINVAL;
448
449 return codec->hw_read(codec, reg);
450 }
451
452 return cache[reg];
453}
454
455static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
456 unsigned int value)
457{
458 u16 *cache = codec->reg_cache;
459 u8 data[4];
460 int ret;
461
462 data[0] = (reg >> 8) & 0xff;
463 data[1] = reg & 0xff;
464 data[2] = (value >> 8) & 0xff;
465 data[3] = value & 0xff;
466
467 if (reg < codec->reg_cache_size)
468 cache[reg] = value;
469
470 if (codec->cache_only) {
471 codec->cache_sync = 1;
472 return 0;
473 }
474
475 ret = codec->hw_write(codec->control_data, data, 4);
476 if (ret == 4)
477 return 0;
478 if (ret < 0)
479 return ret;
480 else
481 return -EIO;
482}
369 483
370static struct { 484static struct {
371 int addr_bits; 485 int addr_bits;
@@ -388,6 +502,7 @@ static struct {
388 { 502 {
389 .addr_bits = 8, .data_bits = 8, 503 .addr_bits = 8, .data_bits = 8,
390 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, 504 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
505 .i2c_read = snd_soc_8_8_read_i2c,
391 }, 506 },
392 { 507 {
393 .addr_bits = 8, .data_bits = 16, 508 .addr_bits = 8, .data_bits = 16,
@@ -400,6 +515,11 @@ static struct {
400 .i2c_read = snd_soc_16_8_read_i2c, 515 .i2c_read = snd_soc_16_8_read_i2c,
401 .spi_write = snd_soc_16_8_spi_write, 516 .spi_write = snd_soc_16_8_spi_write,
402 }, 517 },
518 {
519 .addr_bits = 16, .data_bits = 16,
520 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
521 .i2c_read = snd_soc_16_16_read_i2c,
522 },
403}; 523};
404 524
405/** 525/**
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c8b0556ef431..1ff553bbc063 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -315,7 +315,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
315 315
316 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || 316 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
317 machine->symmetric_rates) { 317 machine->symmetric_rates) {
318 dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 318 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
319 machine->rate); 319 machine->rate);
320 320
321 ret = snd_pcm_hw_constraint_minmax(substream->runtime, 321 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -404,6 +404,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
404 codec_dai->playback.formats & cpu_dai->playback.formats; 404 codec_dai->playback.formats & cpu_dai->playback.formats;
405 runtime->hw.rates = 405 runtime->hw.rates =
406 codec_dai->playback.rates & cpu_dai->playback.rates; 406 codec_dai->playback.rates & cpu_dai->playback.rates;
407 if (codec_dai->playback.rates
408 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
409 runtime->hw.rates |= cpu_dai->playback.rates;
410 if (cpu_dai->playback.rates
411 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
412 runtime->hw.rates |= codec_dai->playback.rates;
407 } else { 413 } else {
408 runtime->hw.rate_min = 414 runtime->hw.rate_min =
409 max(codec_dai->capture.rate_min, 415 max(codec_dai->capture.rate_min,
@@ -421,6 +427,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
421 codec_dai->capture.formats & cpu_dai->capture.formats; 427 codec_dai->capture.formats & cpu_dai->capture.formats;
422 runtime->hw.rates = 428 runtime->hw.rates =
423 codec_dai->capture.rates & cpu_dai->capture.rates; 429 codec_dai->capture.rates & cpu_dai->capture.rates;
430 if (codec_dai->capture.rates
431 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
432 runtime->hw.rates |= cpu_dai->capture.rates;
433 if (cpu_dai->capture.rates
434 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
435 runtime->hw.rates |= codec_dai->capture.rates;
424 } 436 }
425 437
426 snd_pcm_limit_hw_rates(runtime); 438 snd_pcm_limit_hw_rates(runtime);
@@ -454,12 +466,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
454 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, 466 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
455 runtime->hw.rate_max); 467 runtime->hw.rate_max);
456 468
457 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 469 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
458 cpu_dai->playback.active = codec_dai->playback.active = 1; 470 cpu_dai->playback.active++;
459 else 471 codec_dai->playback.active++;
460 cpu_dai->capture.active = codec_dai->capture.active = 1; 472 } else {
461 cpu_dai->active = codec_dai->active = 1; 473 cpu_dai->capture.active++;
462 cpu_dai->runtime = runtime; 474 codec_dai->capture.active++;
475 }
476 cpu_dai->active++;
477 codec_dai->active++;
463 card->codec->active++; 478 card->codec->active++;
464 mutex_unlock(&pcm_mutex); 479 mutex_unlock(&pcm_mutex);
465 return 0; 480 return 0;
@@ -535,15 +550,16 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
535 550
536 mutex_lock(&pcm_mutex); 551 mutex_lock(&pcm_mutex);
537 552
538 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 553 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
539 cpu_dai->playback.active = codec_dai->playback.active = 0; 554 cpu_dai->playback.active--;
540 else 555 codec_dai->playback.active--;
541 cpu_dai->capture.active = codec_dai->capture.active = 0; 556 } else {
542 557 cpu_dai->capture.active--;
543 if (codec_dai->playback.active == 0 && 558 codec_dai->capture.active--;
544 codec_dai->capture.active == 0) {
545 cpu_dai->active = codec_dai->active = 0;
546 } 559 }
560
561 cpu_dai->active--;
562 codec_dai->active--;
547 codec->active--; 563 codec->active--;
548 564
549 /* Muting the DAC suppresses artifacts caused during digital 565 /* Muting the DAC suppresses artifacts caused during digital
@@ -563,7 +579,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
563 579
564 if (platform->pcm_ops->close) 580 if (platform->pcm_ops->close)
565 platform->pcm_ops->close(substream); 581 platform->pcm_ops->close(substream);
566 cpu_dai->runtime = NULL;
567 582
568 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 583 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
569 /* start delayed pop wq here for playback streams */ 584 /* start delayed pop wq here for playback streams */
@@ -801,6 +816,41 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
801 return 0; 816 return 0;
802} 817}
803 818
819/*
820 * soc level wrapper for pointer callback
821 * If cpu_dai, codec_dai, platform driver has the delay callback, than
822 * the runtime->delay will be updated accordingly.
823 */
824static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
825{
826 struct snd_soc_pcm_runtime *rtd = substream->private_data;
827 struct snd_soc_device *socdev = rtd->socdev;
828 struct snd_soc_card *card = socdev->card;
829 struct snd_soc_platform *platform = card->platform;
830 struct snd_soc_dai_link *machine = rtd->dai;
831 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
832 struct snd_soc_dai *codec_dai = machine->codec_dai;
833 struct snd_pcm_runtime *runtime = substream->runtime;
834 snd_pcm_uframes_t offset = 0;
835 snd_pcm_sframes_t delay = 0;
836
837 if (platform->pcm_ops->pointer)
838 offset = platform->pcm_ops->pointer(substream);
839
840 if (cpu_dai->ops->delay)
841 delay += cpu_dai->ops->delay(substream, cpu_dai);
842
843 if (codec_dai->ops->delay)
844 delay += codec_dai->ops->delay(substream, codec_dai);
845
846 if (platform->delay)
847 delay += platform->delay(substream, codec_dai);
848
849 runtime->delay = delay;
850
851 return offset;
852}
853
804/* ASoC PCM operations */ 854/* ASoC PCM operations */
805static struct snd_pcm_ops soc_pcm_ops = { 855static struct snd_pcm_ops soc_pcm_ops = {
806 .open = soc_pcm_open, 856 .open = soc_pcm_open,
@@ -809,6 +859,7 @@ static struct snd_pcm_ops soc_pcm_ops = {
809 .hw_free = soc_pcm_hw_free, 859 .hw_free = soc_pcm_hw_free,
810 .prepare = soc_pcm_prepare, 860 .prepare = soc_pcm_prepare,
811 .trigger = soc_pcm_trigger, 861 .trigger = soc_pcm_trigger,
862 .pointer = soc_pcm_pointer,
812}; 863};
813 864
814#ifdef CONFIG_PM 865#ifdef CONFIG_PM
@@ -858,7 +909,7 @@ static int soc_suspend(struct device *dev)
858 if (cpu_dai->suspend && !cpu_dai->ac97_control) 909 if (cpu_dai->suspend && !cpu_dai->ac97_control)
859 cpu_dai->suspend(cpu_dai); 910 cpu_dai->suspend(cpu_dai);
860 if (platform->suspend) 911 if (platform->suspend)
861 platform->suspend(cpu_dai); 912 platform->suspend(&card->dai_link[i]);
862 } 913 }
863 914
864 /* close any waiting streams and save state */ 915 /* close any waiting streams and save state */
@@ -947,7 +998,7 @@ static void soc_resume_deferred(struct work_struct *work)
947 if (cpu_dai->resume && !cpu_dai->ac97_control) 998 if (cpu_dai->resume && !cpu_dai->ac97_control)
948 cpu_dai->resume(cpu_dai); 999 cpu_dai->resume(cpu_dai);
949 if (platform->resume) 1000 if (platform->resume)
950 platform->resume(cpu_dai); 1001 platform->resume(&card->dai_link[i]);
951 } 1002 }
952 1003
953 if (card->resume_post) 1004 if (card->resume_post)
@@ -1232,26 +1283,25 @@ static int soc_remove(struct platform_device *pdev)
1232 struct snd_soc_platform *platform = card->platform; 1283 struct snd_soc_platform *platform = card->platform;
1233 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 1284 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1234 1285
1235 if (!card->instantiated) 1286 if (card->instantiated) {
1236 return 0; 1287 run_delayed_work(&card->delayed_work);
1237 1288
1238 run_delayed_work(&card->delayed_work); 1289 if (platform->remove)
1290 platform->remove(pdev);
1239 1291
1240 if (platform->remove) 1292 if (codec_dev->remove)
1241 platform->remove(pdev); 1293 codec_dev->remove(pdev);
1242 1294
1243 if (codec_dev->remove) 1295 for (i = 0; i < card->num_links; i++) {
1244 codec_dev->remove(pdev); 1296 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1297 if (cpu_dai->remove)
1298 cpu_dai->remove(pdev, cpu_dai);
1299 }
1245 1300
1246 for (i = 0; i < card->num_links; i++) { 1301 if (card->remove)
1247 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1302 card->remove(pdev);
1248 if (cpu_dai->remove)
1249 cpu_dai->remove(pdev, cpu_dai);
1250 } 1303 }
1251 1304
1252 if (card->remove)
1253 card->remove(pdev);
1254
1255 snd_soc_unregister_card(card); 1305 snd_soc_unregister_card(card);
1256 1306
1257 return 0; 1307 return 0;
@@ -1335,7 +1385,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1335 dai_link->pcm = pcm; 1385 dai_link->pcm = pcm;
1336 pcm->private_data = rtd; 1386 pcm->private_data = rtd;
1337 soc_pcm_ops.mmap = platform->pcm_ops->mmap; 1387 soc_pcm_ops.mmap = platform->pcm_ops->mmap;
1338 soc_pcm_ops.pointer = platform->pcm_ops->pointer;
1339 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; 1388 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
1340 soc_pcm_ops.copy = platform->pcm_ops->copy; 1389 soc_pcm_ops.copy = platform->pcm_ops->copy;
1341 soc_pcm_ops.silence = platform->pcm_ops->silence; 1390 soc_pcm_ops.silence = platform->pcm_ops->silence;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 6c3351095786..476dbe6dabad 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -97,7 +97,6 @@ static void pop_dbg(u32 pop_time, const char *fmt, ...)
97 97
98 if (pop_time) { 98 if (pop_time) {
99 vprintk(fmt, args); 99 vprintk(fmt, args);
100 pop_wait(pop_time);
101 } 100 }
102 101
103 va_end(args); 102 va_end(args);
@@ -314,62 +313,14 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
314 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", 313 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
315 widget->name, widget->power ? "on" : "off", 314 widget->name, widget->power ? "on" : "off",
316 codec->pop_time); 315 codec->pop_time);
317 snd_soc_write(codec, widget->reg, new);
318 pop_wait(codec->pop_time); 316 pop_wait(codec->pop_time);
317 snd_soc_write(codec, widget->reg, new);
319 } 318 }
320 pr_debug("reg %x old %x new %x change %d\n", widget->reg, 319 pr_debug("reg %x old %x new %x change %d\n", widget->reg,
321 old, new, change); 320 old, new, change);
322 return change; 321 return change;
323} 322}
324 323
325/* ramps the volume up or down to minimise pops before or after a
326 * DAPM power event */
327static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
328{
329 const struct snd_kcontrol_new *k = widget->kcontrols;
330
331 if (widget->muted && !power)
332 return 0;
333 if (!widget->muted && power)
334 return 0;
335
336 if (widget->num_kcontrols && k) {
337 struct soc_mixer_control *mc =
338 (struct soc_mixer_control *)k->private_value;
339 unsigned int reg = mc->reg;
340 unsigned int shift = mc->shift;
341 int max = mc->max;
342 unsigned int mask = (1 << fls(max)) - 1;
343 unsigned int invert = mc->invert;
344
345 if (power) {
346 int i;
347 /* power up has happended, increase volume to last level */
348 if (invert) {
349 for (i = max; i > widget->saved_value; i--)
350 snd_soc_update_bits(widget->codec, reg, mask, i);
351 } else {
352 for (i = 0; i < widget->saved_value; i++)
353 snd_soc_update_bits(widget->codec, reg, mask, i);
354 }
355 widget->muted = 0;
356 } else {
357 /* power down is about to occur, decrease volume to mute */
358 int val = snd_soc_read(widget->codec, reg);
359 int i = widget->saved_value = (val >> shift) & mask;
360 if (invert) {
361 for (; i < mask; i++)
362 snd_soc_update_bits(widget->codec, reg, mask, i);
363 } else {
364 for (; i > 0; i--)
365 snd_soc_update_bits(widget->codec, reg, mask, i);
366 }
367 widget->muted = 1;
368 }
369 }
370 return 0;
371}
372
373/* create new dapm mixer control */ 324/* create new dapm mixer control */
374static int dapm_new_mixer(struct snd_soc_codec *codec, 325static int dapm_new_mixer(struct snd_soc_codec *codec,
375 struct snd_soc_dapm_widget *w) 326 struct snd_soc_dapm_widget *w)
@@ -464,20 +415,10 @@ err:
464static int dapm_new_pga(struct snd_soc_codec *codec, 415static int dapm_new_pga(struct snd_soc_codec *codec,
465 struct snd_soc_dapm_widget *w) 416 struct snd_soc_dapm_widget *w)
466{ 417{
467 struct snd_kcontrol *kcontrol; 418 if (w->num_kcontrols)
468 int ret = 0; 419 pr_err("asoc: PGA controls not supported: '%s'\n", w->name);
469
470 if (!w->num_kcontrols)
471 return -EINVAL;
472 420
473 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); 421 return 0;
474 ret = snd_ctl_add(codec->card, kcontrol);
475 if (ret < 0) {
476 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
477 return ret;
478 }
479
480 return ret;
481} 422}
482 423
483/* reset 'walked' bit for each dapm path */ 424/* reset 'walked' bit for each dapm path */
@@ -633,16 +574,8 @@ static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
633 return ret; 574 return ret;
634 } 575 }
635 576
636 /* Lower PGA volume to reduce pops */
637 if (w->id == snd_soc_dapm_pga && !w->power)
638 dapm_set_pga(w, w->power);
639
640 dapm_update_bits(w); 577 dapm_update_bits(w);
641 578
642 /* Raise PGA volume to reduce pops */
643 if (w->id == snd_soc_dapm_pga && w->power)
644 dapm_set_pga(w, w->power);
645
646 /* power up post event */ 579 /* power up post event */
647 if (w->power && w->event && 580 if (w->power && w->event &&
648 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 581 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
@@ -809,10 +742,6 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
809 pr_err("%s: pre event failed: %d\n", 742 pr_err("%s: pre event failed: %d\n",
810 w->name, ret); 743 w->name, ret);
811 } 744 }
812
813 /* Lower PGA volume to reduce pops */
814 if (w->id == snd_soc_dapm_pga && !w->power)
815 dapm_set_pga(w, w->power);
816 } 745 }
817 746
818 if (reg >= 0) { 747 if (reg >= 0) {
@@ -824,10 +753,6 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
824 } 753 }
825 754
826 list_for_each_entry(w, pending, power_list) { 755 list_for_each_entry(w, pending, power_list) {
827 /* Raise PGA volume to reduce pops */
828 if (w->id == snd_soc_dapm_pga && w->power)
829 dapm_set_pga(w, w->power);
830
831 /* power up post event */ 756 /* power up post event */
832 if (w->power && w->event && 757 if (w->power && w->event &&
833 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 758 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
@@ -980,7 +905,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
980 break; 905 break;
981 906
982 default: 907 default:
983 power = w->power_check(w); 908 if (!w->force)
909 power = w->power_check(w);
910 else
911 power = 1;
984 if (power) 912 if (power)
985 sys_power = 1; 913 sys_power = 1;
986 break; 914 break;
@@ -1075,6 +1003,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
1075 1003
1076 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", 1004 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n",
1077 codec->pop_time); 1005 codec->pop_time);
1006 pop_wait(codec->pop_time);
1078 1007
1079 return 0; 1008 return 0;
1080} 1009}
@@ -1337,6 +1266,9 @@ static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
1337 if (!strcmp(w->name, pin)) { 1266 if (!strcmp(w->name, pin)) {
1338 pr_debug("dapm: %s: pin %s\n", codec->name, pin); 1267 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
1339 w->connected = status; 1268 w->connected = status;
1269 /* Allow disabling of forced pins */
1270 if (status == 0)
1271 w->force = 0;
1340 return 0; 1272 return 0;
1341 } 1273 }
1342 } 1274 }
@@ -1593,12 +1525,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1593 unsigned int invert = mc->invert; 1525 unsigned int invert = mc->invert;
1594 unsigned int mask = (1 << fls(max)) - 1; 1526 unsigned int mask = (1 << fls(max)) - 1;
1595 1527
1596 /* return the saved value if we are powered down */
1597 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1598 ucontrol->value.integer.value[0] = widget->saved_value;
1599 return 0;
1600 }
1601
1602 ucontrol->value.integer.value[0] = 1528 ucontrol->value.integer.value[0] =
1603 (snd_soc_read(widget->codec, reg) >> shift) & mask; 1529 (snd_soc_read(widget->codec, reg) >> shift) & mask;
1604 if (shift != rshift) 1530 if (shift != rshift)
@@ -1658,13 +1584,6 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1658 mutex_lock(&widget->codec->mutex); 1584 mutex_lock(&widget->codec->mutex);
1659 widget->value = val; 1585 widget->value = val;
1660 1586
1661 /* save volume value if the widget is powered down */
1662 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1663 widget->saved_value = val;
1664 mutex_unlock(&widget->codec->mutex);
1665 return 1;
1666 }
1667
1668 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { 1587 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
1669 if (val) 1588 if (val)
1670 /* new connection */ 1589 /* new connection */
@@ -2134,6 +2053,36 @@ int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
2134EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); 2053EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
2135 2054
2136/** 2055/**
2056 * snd_soc_dapm_force_enable_pin - force a pin to be enabled
2057 * @codec: SoC codec
2058 * @pin: pin name
2059 *
2060 * Enables input/output pin regardless of any other state. This is
2061 * intended for use with microphone bias supplies used in microphone
2062 * jack detection.
2063 *
2064 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2065 * do any widget power switching.
2066 */
2067int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec, const char *pin)
2068{
2069 struct snd_soc_dapm_widget *w;
2070
2071 list_for_each_entry(w, &codec->dapm_widgets, list) {
2072 if (!strcmp(w->name, pin)) {
2073 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
2074 w->connected = 1;
2075 w->force = 1;
2076 return 0;
2077 }
2078 }
2079
2080 pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
2081 return -EINVAL;
2082}
2083EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
2084
2085/**
2137 * snd_soc_dapm_disable_pin - disable pin. 2086 * snd_soc_dapm_disable_pin - disable pin.
2138 * @codec: SoC codec 2087 * @codec: SoC codec
2139 * @pin: pin name 2088 * @pin: pin name
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 3c07a94c2e30..f8fd22cc70bc 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
37{ 37{
38 jack->card = card; 38 jack->card = card;
39 INIT_LIST_HEAD(&jack->pins); 39 INIT_LIST_HEAD(&jack->pins);
40 BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
40 41
41 return snd_jack_new(card->codec->card, id, type, &jack->jack); 42 return snd_jack_new(card->codec->card, id, type, &jack->jack);
42} 43}
@@ -93,6 +94,9 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
93 snd_soc_dapm_disable_pin(codec, pin->pin); 94 snd_soc_dapm_disable_pin(codec, pin->pin);
94 } 95 }
95 96
97 /* Report before the DAPM sync to help users updating micbias status */
98 blocking_notifier_call_chain(&jack->notifier, status, NULL);
99
96 snd_soc_dapm_sync(codec); 100 snd_soc_dapm_sync(codec);
97 101
98 snd_jack_report(jack->jack, status); 102 snd_jack_report(jack->jack, status);
@@ -143,6 +147,40 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
143} 147}
144EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); 148EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins);
145 149
150/**
151 * snd_soc_jack_notifier_register - Register a notifier for jack status
152 *
153 * @jack: ASoC jack
154 * @nb: Notifier block to register
155 *
156 * Register for notification of the current status of the jack. Note
157 * that it is not possible to report additional jack events in the
158 * callback from the notifier, this is intended to support
159 * applications such as enabling electrical detection only when a
160 * mechanical detection event has occurred.
161 */
162void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
163 struct notifier_block *nb)
164{
165 blocking_notifier_chain_register(&jack->notifier, nb);
166}
167EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_register);
168
169/**
170 * snd_soc_jack_notifier_unregister - Unregister a notifier for jack status
171 *
172 * @jack: ASoC jack
173 * @nb: Notifier block to unregister
174 *
175 * Stop notifying for status changes.
176 */
177void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
178 struct notifier_block *nb)
179{
180 blocking_notifier_chain_unregister(&jack->notifier, nb);
181}
182EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister);
183
146#ifdef CONFIG_GPIOLIB 184#ifdef CONFIG_GPIOLIB
147/* gpio detect */ 185/* gpio detect */
148static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) 186static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)