aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/ep93xx
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ep93xx')
-rw-r--r--sound/soc/ep93xx/Kconfig16
-rw-r--r--sound/soc/ep93xx/Makefile4
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c468
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c34
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.h18
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c37
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.h2
-rw-r--r--sound/soc/ep93xx/simone.c89
-rw-r--r--sound/soc/ep93xx/snappercl15.c24
9 files changed, 627 insertions, 65 deletions
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index f617f560f46b..57429041189c 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -3,11 +3,16 @@ config SND_EP93XX_SOC
3 depends on ARCH_EP93XX && SND_SOC 3 depends on ARCH_EP93XX && SND_SOC
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the EP93xx I2S interface. 6 the EP93xx I2S or AC97 interfaces.
7 7
8config SND_EP93XX_SOC_I2S 8config SND_EP93XX_SOC_I2S
9 tristate 9 tristate
10 10
11config SND_EP93XX_SOC_AC97
12 tristate
13 select AC97_BUS
14 select SND_SOC_AC97_BUS
15
11config SND_EP93XX_SOC_SNAPPERCL15 16config SND_EP93XX_SOC_SNAPPERCL15
12 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" 17 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
13 depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 18 depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
@@ -16,3 +21,12 @@ config SND_EP93XX_SOC_SNAPPERCL15
16 help 21 help
17 Say Y or M here if you want to add support for I2S audio on the 22 Say Y or M here if you want to add support for I2S audio on the
18 Bluewater Systems Snapper CL15 module. 23 Bluewater Systems Snapper CL15 module.
24
25config SND_EP93XX_SOC_SIMONE
26 tristate "SoC Audio support for Simplemachines Sim.One board"
27 depends on SND_EP93XX_SOC && MACH_SIM_ONE
28 select SND_EP93XX_SOC_AC97
29 select SND_SOC_AC97_CODEC
30 help
31 Say Y or M here if you want to add support for AC97 audio on the
32 Simplemachines Sim.One board.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
index 272e60f57b9a..8e7977fb6b7d 100644
--- a/sound/soc/ep93xx/Makefile
+++ b/sound/soc/ep93xx/Makefile
@@ -1,11 +1,15 @@
1# EP93xx Platform Support 1# EP93xx Platform Support
2snd-soc-ep93xx-objs := ep93xx-pcm.o 2snd-soc-ep93xx-objs := ep93xx-pcm.o
3snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o 3snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o
4snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o
4 5
5obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o 6obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o
6obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o 7obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o
8obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o
7 9
8# EP93XX Machine Support 10# EP93XX Machine Support
9snd-soc-snappercl15-objs := snappercl15.o 11snd-soc-snappercl15-objs := snappercl15.o
12snd-soc-simone-objs := simone.o
10 13
11obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o 14obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
15obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
new file mode 100644
index 000000000000..68a0bae1208a
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -0,0 +1,468 @@
1/*
2 * ASoC driver for Cirrus Logic EP93xx AC97 controller.
3 *
4 * Copyright (c) 2010 Mika Westerberg
5 *
6 * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/io.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19
20#include <sound/core.h>
21#include <sound/ac97_codec.h>
22#include <sound/soc.h>
23
24#include <mach/dma.h>
25#include "ep93xx-pcm.h"
26
27/*
28 * Per channel (1-4) registers.
29 */
30#define AC97CH(n) (((n) - 1) * 0x20)
31
32#define AC97DR(n) (AC97CH(n) + 0x0000)
33
34#define AC97RXCR(n) (AC97CH(n) + 0x0004)
35#define AC97RXCR_REN BIT(0)
36#define AC97RXCR_RX3 BIT(3)
37#define AC97RXCR_RX4 BIT(4)
38#define AC97RXCR_CM BIT(15)
39
40#define AC97TXCR(n) (AC97CH(n) + 0x0008)
41#define AC97TXCR_TEN BIT(0)
42#define AC97TXCR_TX3 BIT(3)
43#define AC97TXCR_TX4 BIT(4)
44#define AC97TXCR_CM BIT(15)
45
46#define AC97SR(n) (AC97CH(n) + 0x000c)
47#define AC97SR_TXFE BIT(1)
48#define AC97SR_TXUE BIT(6)
49
50#define AC97RISR(n) (AC97CH(n) + 0x0010)
51#define AC97ISR(n) (AC97CH(n) + 0x0014)
52#define AC97IE(n) (AC97CH(n) + 0x0018)
53
54/*
55 * Global AC97 controller registers.
56 */
57#define AC97S1DATA 0x0080
58#define AC97S2DATA 0x0084
59#define AC97S12DATA 0x0088
60
61#define AC97RGIS 0x008c
62#define AC97GIS 0x0090
63#define AC97IM 0x0094
64/*
65 * Common bits for RGIS, GIS and IM registers.
66 */
67#define AC97_SLOT2RXVALID BIT(1)
68#define AC97_CODECREADY BIT(5)
69#define AC97_SLOT2TXCOMPLETE BIT(6)
70
71#define AC97EOI 0x0098
72#define AC97EOI_WINT BIT(0)
73#define AC97EOI_CODECREADY BIT(1)
74
75#define AC97GCR 0x009c
76#define AC97GCR_AC97IFE BIT(0)
77
78#define AC97RESET 0x00a0
79#define AC97RESET_TIMEDRESET BIT(0)
80
81#define AC97SYNC 0x00a4
82#define AC97SYNC_TIMEDSYNC BIT(0)
83
84#define AC97_TIMEOUT msecs_to_jiffies(5)
85
86/**
87 * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
88 * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
89 * @dev: pointer to the platform device dev structure
90 * @mem: physical memory resource for the registers
91 * @regs: mapped AC97 controller registers
92 * @irq: AC97 interrupt number
93 * @done: bus ops wait here for an interrupt
94 */
95struct ep93xx_ac97_info {
96 struct mutex lock;
97 struct device *dev;
98 struct resource *mem;
99 void __iomem *regs;
100 int irq;
101 struct completion done;
102};
103
104/* currently ALSA only supports a single AC97 device */
105static struct ep93xx_ac97_info *ep93xx_ac97_info;
106
107static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
108 .name = "ac97-pcm-out",
109 .dma_port = EP93XX_DMA_M2P_PORT_AAC1,
110};
111
112static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
113 .name = "ac97-pcm-in",
114 .dma_port = EP93XX_DMA_M2P_PORT_AAC1,
115};
116
117static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
118 unsigned reg)
119{
120 return __raw_readl(info->regs + reg);
121}
122
123static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
124 unsigned reg, unsigned val)
125{
126 __raw_writel(val, info->regs + reg);
127}
128
129static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
130 unsigned short reg)
131{
132 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
133 unsigned short val;
134
135 mutex_lock(&info->lock);
136
137 ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
138 ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
139 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
140 dev_warn(info->dev, "timeout reading register %x\n", reg);
141 mutex_unlock(&info->lock);
142 return -ETIMEDOUT;
143 }
144 val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
145
146 mutex_unlock(&info->lock);
147 return val;
148}
149
150static void ep93xx_ac97_write(struct snd_ac97 *ac97,
151 unsigned short reg,
152 unsigned short val)
153{
154 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
155
156 mutex_lock(&info->lock);
157
158 /*
159 * Writes to the codec need to be done so that slot 2 is filled in
160 * before slot 1.
161 */
162 ep93xx_ac97_write_reg(info, AC97S2DATA, val);
163 ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
164
165 ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
166 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
167 dev_warn(info->dev, "timeout writing register %x\n", reg);
168
169 mutex_unlock(&info->lock);
170}
171
172static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
173{
174 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
175
176 mutex_lock(&info->lock);
177
178 /*
179 * We are assuming that before this functions gets called, the codec
180 * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
181 * control the SYNC signal directly via AC97SYNC register. Using
182 * TIMEDSYNC the controller will keep the SYNC high > 1us.
183 */
184 ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
185 ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
186 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
187 dev_warn(info->dev, "codec warm reset timeout\n");
188
189 mutex_unlock(&info->lock);
190}
191
192static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
193{
194 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
195
196 mutex_lock(&info->lock);
197
198 /*
199 * For doing cold reset, we disable the AC97 controller interface, clear
200 * WINT and CODECREADY bits, and finally enable the interface again.
201 */
202 ep93xx_ac97_write_reg(info, AC97GCR, 0);
203 ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
204 ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
205
206 /*
207 * Now, assert the reset and wait for the codec to become ready.
208 */
209 ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
210 ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
211 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
212 dev_warn(info->dev, "codec cold reset timeout\n");
213
214 /*
215 * Give the codec some time to come fully out from the reset. This way
216 * we ensure that the subsequent reads/writes will work.
217 */
218 usleep_range(15000, 20000);
219
220 mutex_unlock(&info->lock);
221}
222
223static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
224{
225 struct ep93xx_ac97_info *info = dev_id;
226 unsigned status, mask;
227
228 /*
229 * Just mask out the interrupt and wake up the waiting thread.
230 * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
231 * the waiting thread.
232 */
233 status = ep93xx_ac97_read_reg(info, AC97GIS);
234 mask = ep93xx_ac97_read_reg(info, AC97IM);
235 mask &= ~status;
236 ep93xx_ac97_write_reg(info, AC97IM, mask);
237
238 complete(&info->done);
239 return IRQ_HANDLED;
240}
241
242struct snd_ac97_bus_ops soc_ac97_ops = {
243 .read = ep93xx_ac97_read,
244 .write = ep93xx_ac97_write,
245 .reset = ep93xx_ac97_cold_reset,
246 .warm_reset = ep93xx_ac97_warm_reset,
247};
248EXPORT_SYMBOL_GPL(soc_ac97_ops);
249
250static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
251 int cmd, struct snd_soc_dai *dai)
252{
253 struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
254 unsigned v = 0;
255
256
257 switch (cmd) {
258 case SNDRV_PCM_TRIGGER_START:
259 case SNDRV_PCM_TRIGGER_RESUME:
260 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
261 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
262 /*
263 * Enable compact mode, TX slots 3 & 4, and the TX FIFO
264 * itself.
265 */
266 v |= AC97TXCR_CM;
267 v |= AC97TXCR_TX3 | AC97TXCR_TX4;
268 v |= AC97TXCR_TEN;
269 ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
270 } else {
271 /*
272 * Enable compact mode, RX slots 3 & 4, and the RX FIFO
273 * itself.
274 */
275 v |= AC97RXCR_CM;
276 v |= AC97RXCR_RX3 | AC97RXCR_RX4;
277 v |= AC97RXCR_REN;
278 ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
279 }
280 break;
281
282 case SNDRV_PCM_TRIGGER_STOP:
283 case SNDRV_PCM_TRIGGER_SUSPEND:
284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
285 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
286 /*
287 * As per Cirrus EP93xx errata described below:
288 *
289 * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
290 *
291 * we will wait for the TX FIFO to be empty before
292 * clearing the TEN bit.
293 */
294 unsigned long timeout = jiffies + AC97_TIMEOUT;
295
296 do {
297 v = ep93xx_ac97_read_reg(info, AC97SR(1));
298 if (time_after(jiffies, timeout)) {
299 dev_warn(info->dev, "TX timeout\n");
300 break;
301 }
302 } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
303
304 /* disable the TX FIFO */
305 ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
306 } else {
307 /* disable the RX FIFO */
308 ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
309 }
310 break;
311
312 default:
313 dev_warn(info->dev, "unknown command %d\n", cmd);
314 return -EINVAL;
315 }
316
317 return 0;
318}
319
320static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
321 struct snd_soc_dai *dai)
322{
323 struct ep93xx_pcm_dma_params *dma_data;
324
325 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
326 dma_data = &ep93xx_ac97_pcm_out;
327 else
328 dma_data = &ep93xx_ac97_pcm_in;
329
330 snd_soc_dai_set_dma_data(dai, substream, dma_data);
331 return 0;
332}
333
334static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
335 .startup = ep93xx_ac97_startup,
336 .trigger = ep93xx_ac97_trigger,
337};
338
339struct snd_soc_dai_driver ep93xx_ac97_dai = {
340 .name = "ep93xx-ac97",
341 .id = 0,
342 .ac97_control = 1,
343 .playback = {
344 .stream_name = "AC97 Playback",
345 .channels_min = 2,
346 .channels_max = 2,
347 .rates = SNDRV_PCM_RATE_8000_48000,
348 .formats = SNDRV_PCM_FMTBIT_S16_LE,
349 },
350 .capture = {
351 .stream_name = "AC97 Capture",
352 .channels_min = 2,
353 .channels_max = 2,
354 .rates = SNDRV_PCM_RATE_8000_48000,
355 .formats = SNDRV_PCM_FMTBIT_S16_LE,
356 },
357 .ops = &ep93xx_ac97_dai_ops,
358};
359
360static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
361{
362 struct ep93xx_ac97_info *info;
363 int ret;
364
365 info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL);
366 if (!info)
367 return -ENOMEM;
368
369 dev_set_drvdata(&pdev->dev, info);
370
371 mutex_init(&info->lock);
372 init_completion(&info->done);
373 info->dev = &pdev->dev;
374
375 info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
376 if (!info->mem) {
377 ret = -ENXIO;
378 goto fail_free_info;
379 }
380
381 info->irq = platform_get_irq(pdev, 0);
382 if (!info->irq) {
383 ret = -ENXIO;
384 goto fail_free_info;
385 }
386
387 if (!request_mem_region(info->mem->start, resource_size(info->mem),
388 pdev->name)) {
389 ret = -EBUSY;
390 goto fail_free_info;
391 }
392
393 info->regs = ioremap(info->mem->start, resource_size(info->mem));
394 if (!info->regs) {
395 ret = -ENOMEM;
396 goto fail_release_mem;
397 }
398
399 ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH,
400 pdev->name, info);
401 if (ret)
402 goto fail_unmap_mem;
403
404 ep93xx_ac97_info = info;
405 platform_set_drvdata(pdev, info);
406
407 ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
408 if (ret)
409 goto fail_free_irq;
410
411 return 0;
412
413fail_free_irq:
414 platform_set_drvdata(pdev, NULL);
415 free_irq(info->irq, info);
416fail_unmap_mem:
417 iounmap(info->regs);
418fail_release_mem:
419 release_mem_region(info->mem->start, resource_size(info->mem));
420fail_free_info:
421 kfree(info);
422
423 return ret;
424}
425
426static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
427{
428 struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
429
430 snd_soc_unregister_dai(&pdev->dev);
431
432 /* disable the AC97 controller */
433 ep93xx_ac97_write_reg(info, AC97GCR, 0);
434
435 free_irq(info->irq, info);
436 iounmap(info->regs);
437 release_mem_region(info->mem->start, resource_size(info->mem));
438 platform_set_drvdata(pdev, NULL);
439 kfree(info);
440
441 return 0;
442}
443
444static struct platform_driver ep93xx_ac97_driver = {
445 .probe = ep93xx_ac97_probe,
446 .remove = __devexit_p(ep93xx_ac97_remove),
447 .driver = {
448 .name = "ep93xx-ac97",
449 .owner = THIS_MODULE,
450 },
451};
452
453static int __init ep93xx_ac97_init(void)
454{
455 return platform_driver_register(&ep93xx_ac97_driver);
456}
457module_init(ep93xx_ac97_init);
458
459static void __exit ep93xx_ac97_exit(void)
460{
461 platform_driver_unregister(&ep93xx_ac97_driver);
462}
463module_exit(ep93xx_ac97_exit);
464
465MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
466MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
467MODULE_LICENSE("GPL");
468MODULE_ALIAS("platform:ep93xx-ac97");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 00b946632184..4f4873359613 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -31,7 +31,6 @@
31#include <mach/dma.h> 31#include <mach/dma.h>
32 32
33#include "ep93xx-pcm.h" 33#include "ep93xx-pcm.h"
34#include "ep93xx-i2s.h"
35 34
36#define EP93XX_I2S_TXCLKCFG 0x00 35#define EP93XX_I2S_TXCLKCFG 0x00
37#define EP93XX_I2S_RXCLKCFG 0x04 36#define EP93XX_I2S_RXCLKCFG 0x04
@@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai) 144 struct snd_soc_dai *dai)
146{ 145{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 147 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
149 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; 148 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
150 149
151 snd_soc_dai_set_dma_data(cpu_dai, substream, 150 snd_soc_dai_set_dma_data(cpu_dai, substream,
152 &info->dma_params[substream->stream]); 151 &info->dma_params[substream->stream]);
@@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
156static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, 155static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
157 struct snd_soc_dai *dai) 156 struct snd_soc_dai *dai)
158{ 157{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data; 158 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
160 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
161 159
162 ep93xx_i2s_disable(info, substream->stream); 160 ep93xx_i2s_disable(info, substream->stream);
163} 161}
@@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
165static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 163static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
166 unsigned int fmt) 164 unsigned int fmt)
167{ 165{
168 struct ep93xx_i2s_info *info = cpu_dai->private_data; 166 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
169 unsigned int clk_cfg, lin_ctrl; 167 unsigned int clk_cfg, lin_ctrl;
170 168
171 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); 169 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
@@ -242,9 +240,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
242 struct snd_pcm_hw_params *params, 240 struct snd_pcm_hw_params *params,
243 struct snd_soc_dai *dai) 241 struct snd_soc_dai *dai)
244{ 242{
245 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
246 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
247 struct ep93xx_i2s_info *info = cpu_dai->private_data;
248 unsigned word_len, div, sdiv, lrdiv; 244 unsigned word_len, div, sdiv, lrdiv;
249 int found = 0, err; 245 int found = 0, err;
250 246
@@ -302,7 +298,7 @@ out:
302static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 298static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
303 unsigned int freq, int dir) 299 unsigned int freq, int dir)
304{ 300{
305 struct ep93xx_i2s_info *info = cpu_dai->private_data; 301 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
306 302
307 if (dir == SND_SOC_CLOCK_IN || clk_id != 0) 303 if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
308 return -EINVAL; 304 return -EINVAL;
@@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
313#ifdef CONFIG_PM 309#ifdef CONFIG_PM
314static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) 310static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
315{ 311{
316 struct ep93xx_i2s_info *info = dai->private_data; 312 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
317 313
318 if (!dai->active) 314 if (!dai->active)
319 return; 315 return;
@@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
324 320
325static int ep93xx_i2s_resume(struct snd_soc_dai *dai) 321static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
326{ 322{
327 struct ep93xx_i2s_info *info = dai->private_data; 323 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
328 324
329 if (!dai->active) 325 if (!dai->active)
330 return; 326 return;
@@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
349 SNDRV_PCM_FMTBIT_S24_LE | \ 345 SNDRV_PCM_FMTBIT_S24_LE | \
350 SNDRV_PCM_FMTBIT_S32_LE) 346 SNDRV_PCM_FMTBIT_S32_LE)
351 347
352struct snd_soc_dai ep93xx_i2s_dai = { 348static struct snd_soc_dai_driver ep93xx_i2s_dai = {
353 .name = "ep93xx-i2s",
354 .id = 0,
355 .symmetric_rates= 1, 349 .symmetric_rates= 1,
356 .suspend = ep93xx_i2s_suspend, 350 .suspend = ep93xx_i2s_suspend,
357 .resume = ep93xx_i2s_resume, 351 .resume = ep93xx_i2s_resume,
@@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = {
369 }, 363 },
370 .ops = &ep93xx_i2s_dai_ops, 364 .ops = &ep93xx_i2s_dai_ops,
371}; 365};
372EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
373 366
374static int ep93xx_i2s_probe(struct platform_device *pdev) 367static int ep93xx_i2s_probe(struct platform_device *pdev)
375{ 368{
@@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
383 goto fail; 376 goto fail;
384 } 377 }
385 378
386 ep93xx_i2s_dai.dev = &pdev->dev; 379 dev_set_drvdata(&pdev->dev, info);
387 ep93xx_i2s_dai.private_data = info;
388 info->dma_params = ep93xx_i2s_dma_params; 380 info->dma_params = ep93xx_i2s_dma_params;
389 381
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 382 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
424 goto fail_put_sclk; 416 goto fail_put_sclk;
425 } 417 }
426 418
427 err = snd_soc_register_dai(&ep93xx_i2s_dai); 419 err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
428 if (err) 420 if (err)
429 goto fail_put_lrclk; 421 goto fail_put_lrclk;
430 422
@@ -447,9 +439,9 @@ fail:
447 439
448static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) 440static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
449{ 441{
450 struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; 442 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
451 443
452 snd_soc_unregister_dai(&ep93xx_i2s_dai); 444 snd_soc_unregister_dai(&pdev->dev);
453 clk_put(info->lrclk); 445 clk_put(info->lrclk);
454 clk_put(info->sclk); 446 clk_put(info->sclk);
455 clk_put(info->mclk); 447 clk_put(info->mclk);
diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h
deleted file mode 100644
index 3bd4ebfaa1de..000000000000
--- a/sound/soc/ep93xx/ep93xx-i2s.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * linux/sound/soc/ep93xx-i2s.h
3 * EP93xx I2S driver
4 *
5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#ifndef _EP93XX_SND_SOC_I2S_H
14#define _EP93XX_SND_SOC_I2S_H
15
16extern struct snd_soc_dai ep93xx_i2s_dai;
17
18#endif /* _EP93XX_SND_SOC_I2S_H */
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 4ba938400791..2f121ddbe4bb 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie,
95static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 95static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
96{ 96{
97 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; 97 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
98 struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; 98 struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
99 struct ep93xx_pcm_dma_params *dma_params; 99 struct ep93xx_pcm_dma_params *dma_params;
100 struct ep93xx_runtime_data *rtd; 100 struct ep93xx_runtime_data *rtd;
101 int ret; 101 int ret;
@@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
276 if (!card->dev->coherent_dma_mask) 276 if (!card->dev->coherent_dma_mask)
277 card->dev->coherent_dma_mask = 0xffffffff; 277 card->dev->coherent_dma_mask = 0xffffffff;
278 278
279 if (dai->playback.channels_min) { 279 if (dai->driver->playback.channels_min) {
280 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 280 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
281 SNDRV_PCM_STREAM_PLAYBACK); 281 SNDRV_PCM_STREAM_PLAYBACK);
282 if (ret) 282 if (ret)
283 return ret; 283 return ret;
284 } 284 }
285 285
286 if (dai->capture.channels_min) { 286 if (dai->driver->capture.channels_min) {
287 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 287 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
288 SNDRV_PCM_STREAM_CAPTURE); 288 SNDRV_PCM_STREAM_CAPTURE);
289 if (ret) 289 if (ret)
@@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
293 return 0; 293 return 0;
294} 294}
295 295
296struct snd_soc_platform ep93xx_soc_platform = { 296static struct snd_soc_platform_driver ep93xx_soc_platform = {
297 .name = "ep93xx-audio", 297 .ops = &ep93xx_pcm_ops,
298 .pcm_ops = &ep93xx_pcm_ops,
299 .pcm_new = &ep93xx_pcm_new, 298 .pcm_new = &ep93xx_pcm_new,
300 .pcm_free = &ep93xx_pcm_free_dma_buffers, 299 .pcm_free = &ep93xx_pcm_free_dma_buffers,
301}; 300};
302EXPORT_SYMBOL_GPL(ep93xx_soc_platform); 301
302static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
303{
304 return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
305}
306
307static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
308{
309 snd_soc_unregister_platform(&pdev->dev);
310 return 0;
311}
312
313static struct platform_driver ep93xx_pcm_driver = {
314 .driver = {
315 .name = "ep93xx-pcm-audio",
316 .owner = THIS_MODULE,
317 },
318
319 .probe = ep93xx_soc_platform_probe,
320 .remove = __devexit_p(ep93xx_soc_platform_remove),
321};
303 322
304static int __init ep93xx_soc_platform_init(void) 323static int __init ep93xx_soc_platform_init(void)
305{ 324{
306 return snd_soc_register_platform(&ep93xx_soc_platform); 325 return platform_driver_register(&ep93xx_pcm_driver);
307} 326}
308 327
309static void __exit ep93xx_soc_platform_exit(void) 328static void __exit ep93xx_soc_platform_exit(void)
310{ 329{
311 snd_soc_unregister_platform(&ep93xx_soc_platform); 330 platform_driver_unregister(&ep93xx_pcm_driver);
312} 331}
313 332
314module_init(ep93xx_soc_platform_init); 333module_init(ep93xx_soc_platform_init);
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h
index 4ffdd3f62fe9..111e1121ecb8 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.h
+++ b/sound/soc/ep93xx/ep93xx-pcm.h
@@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params {
17 int dma_port; 17 int dma_port;
18}; 18};
19 19
20extern struct snd_soc_platform ep93xx_soc_platform;
21
22#endif /* _EP93XX_SND_SOC_PCM_H */ 20#endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c
new file mode 100644
index 000000000000..4b0d19913728
--- /dev/null
+++ b/sound/soc/ep93xx/simone.c
@@ -0,0 +1,89 @@
1/*
2 * simone.c -- ASoC audio for Simplemachines Sim.One board
3 *
4 * Copyright (c) 2010 Mika Westerberg
5 *
6 * Based on snappercl15 machine driver by Ryan Mallon.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20
21#include <asm/mach-types.h>
22#include <mach/hardware.h>
23
24#include "ep93xx-pcm.h"
25
26static struct snd_soc_dai_link simone_dai = {
27 .name = "AC97",
28 .stream_name = "AC97 HiFi",
29 .cpu_dai_name = "ep93xx-ac97",
30 .codec_dai_name = "ac97-hifi",
31 .codec_name = "ac97-codec",
32 .platform_name = "ep93xx-pcm-audio",
33};
34
35static struct snd_soc_card snd_soc_simone = {
36 .name = "Sim.One",
37 .dai_link = &simone_dai,
38 .num_links = 1,
39};
40
41static struct platform_device *simone_snd_ac97_device;
42static struct platform_device *simone_snd_device;
43
44static int __init simone_init(void)
45{
46 int ret;
47
48 if (!machine_is_sim_one())
49 return -ENODEV;
50
51 simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1);
52 if (!simone_snd_ac97_device)
53 return -ENOMEM;
54
55 ret = platform_device_add(simone_snd_ac97_device);
56 if (ret)
57 goto fail;
58
59 simone_snd_device = platform_device_alloc("soc-audio", -1);
60 if (!simone_snd_device) {
61 ret = -ENOMEM;
62 goto fail;
63 }
64
65 platform_set_drvdata(simone_snd_device, &snd_soc_simone);
66 ret = platform_device_add(simone_snd_device);
67 if (ret) {
68 platform_device_put(simone_snd_device);
69 goto fail;
70 }
71
72 return ret;
73
74fail:
75 platform_device_put(simone_snd_ac97_device);
76 return ret;
77}
78module_init(simone_init);
79
80static void __exit simone_exit(void)
81{
82 platform_device_unregister(simone_snd_device);
83 platform_device_unregister(simone_snd_ac97_device);
84}
85module_exit(simone_exit);
86
87MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
88MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
89MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index 64955340ff75..28ab5ff772ac 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -22,7 +22,6 @@
22 22
23#include "../codecs/tlv320aic23.h" 23#include "../codecs/tlv320aic23.h"
24#include "ep93xx-pcm.h" 24#include "ep93xx-pcm.h"
25#include "ep93xx-i2s.h"
26 25
27#define CODEC_CLOCK 5644800 26#define CODEC_CLOCK 5644800
28 27
@@ -30,8 +29,8 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream,
30 struct snd_pcm_hw_params *params) 29 struct snd_pcm_hw_params *params)
31{ 30{
32 struct snd_soc_pcm_runtime *rtd = substream->private_data; 31 struct snd_soc_pcm_runtime *rtd = substream->private_data;
33 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 32 struct snd_soc_dai *codec_dai = rtd->codec_dai;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 33 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
35 int err; 34 int err;
36 35
37 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 36 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
@@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
77 {"MICIN", NULL, "Mic Jack"}, 76 {"MICIN", NULL, "Mic Jack"},
78}; 77};
79 78
80static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) 79static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
81{ 80{
81 struct snd_soc_codec *codec = rtd->codec;
82
82 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 83 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
83 ARRAY_SIZE(tlv320aic23_dapm_widgets)); 84 ARRAY_SIZE(tlv320aic23_dapm_widgets));
84 85
@@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)
89static struct snd_soc_dai_link snappercl15_dai = { 90static struct snd_soc_dai_link snappercl15_dai = {
90 .name = "tlv320aic23", 91 .name = "tlv320aic23",
91 .stream_name = "AIC23", 92 .stream_name = "AIC23",
92 .cpu_dai = &ep93xx_i2s_dai, 93 .cpu_dai_name = "ep93xx-i2s",
93 .codec_dai = &tlv320aic23_dai, 94 .codec_dai_name = "tlv320aic23-hifi",
95 .codec_name = "tlv320aic23-codec.0-001a",
96 .platform_name = "ep93xx-pcm-audio",
94 .init = snappercl15_tlv320aic23_init, 97 .init = snappercl15_tlv320aic23_init,
95 .ops = &snappercl15_ops, 98 .ops = &snappercl15_ops,
96}; 99};
97 100
98static struct snd_soc_card snd_soc_snappercl15 = { 101static struct snd_soc_card snd_soc_snappercl15 = {
99 .name = "Snapper CL15", 102 .name = "Snapper CL15",
100 .platform = &ep93xx_soc_platform,
101 .dai_link = &snappercl15_dai, 103 .dai_link = &snappercl15_dai,
102 .num_links = 1, 104 .num_links = 1,
103}; 105};
104 106
105static struct snd_soc_device snappercl15_snd_devdata = {
106 .card = &snd_soc_snappercl15,
107 .codec_dev = &soc_codec_dev_tlv320aic23,
108};
109
110static struct platform_device *snappercl15_snd_device; 107static struct platform_device *snappercl15_snd_device;
111 108
112static int __init snappercl15_init(void) 109static int __init snappercl15_init(void)
@@ -126,8 +123,7 @@ static int __init snappercl15_init(void)
126 if (!snappercl15_snd_device) 123 if (!snappercl15_snd_device)
127 return -ENOMEM; 124 return -ENOMEM;
128 125
129 platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); 126 platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);
130 snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev;
131 ret = platform_device_add(snappercl15_snd_device); 127 ret = platform_device_add(snappercl15_snd_device);
132 if (ret) 128 if (ret)
133 platform_device_put(snappercl15_snd_device); 129 platform_device_put(snappercl15_snd_device);