aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/ep93xx
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ep93xx')
-rw-r--r--sound/soc/ep93xx/Kconfig25
-rw-r--r--sound/soc/ep93xx/Makefile6
-rw-r--r--sound/soc/ep93xx/edb93xx.c142
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c467
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c81
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.h18
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c41
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.h2
-rw-r--r--sound/soc/ep93xx/simone.c91
-rw-r--r--sound/soc/ep93xx/snappercl15.c30
10 files changed, 811 insertions, 92 deletions
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index f617f560f46b..91a28de94109 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,21 @@ 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.
33
34config SND_EP93XX_SOC_EDB93XX
35 tristate "SoC Audio support for Cirrus Logic EDB93xx boards"
36 depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A)
37 select SND_EP93XX_SOC_I2S
38 select SND_SOC_CS4271
39 help
40 Say Y or M here if you want to add support for I2S audio on the
41 Cirrus Logic EDB93xx boards.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
index 272e60f57b9a..5514146cbdf0 100644
--- a/sound/soc/ep93xx/Makefile
+++ b/sound/soc/ep93xx/Makefile
@@ -1,11 +1,17 @@
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
13snd-soc-edb93xx-objs := edb93xx.o
10 14
11obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o 15obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
16obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
17obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
new file mode 100644
index 000000000000..d3aa15119d26
--- /dev/null
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -0,0 +1,142 @@
1/*
2 * SoC audio for EDB93xx
3 *
4 * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
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 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * This driver support CS4271 codec being master or slave, working
17 * in control port mode, connected either via SPI or I2C.
18 * The data format accepted is I2S or left-justified.
19 * DAPM support not implemented.
20 */
21
22#include <linux/platform_device.h>
23#include <linux/gpio.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include "ep93xx-pcm.h"
30
31#define edb93xx_has_audio() (machine_is_edb9301() || \
32 machine_is_edb9302() || \
33 machine_is_edb9302a() || \
34 machine_is_edb9307a() || \
35 machine_is_edb9315a())
36
37static int edb93xx_hw_params(struct snd_pcm_substream *substream,
38 struct snd_pcm_hw_params *params)
39{
40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
43 int err;
44 unsigned int mclk_rate;
45 unsigned int rate = params_rate(params);
46
47 /*
48 * According to CS4271 datasheet we use MCLK/LRCK=256 for
49 * rates below 50kHz and 128 for higher sample rates
50 */
51 if (rate < 50000)
52 mclk_rate = rate * 64 * 4;
53 else
54 mclk_rate = rate * 64 * 2;
55
56 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_IF |
58 SND_SOC_DAIFMT_CBS_CFS);
59 if (err)
60 return err;
61
62 err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
63 SND_SOC_DAIFMT_NB_IF |
64 SND_SOC_DAIFMT_CBS_CFS);
65 if (err)
66 return err;
67
68 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
69 SND_SOC_CLOCK_IN);
70 if (err)
71 return err;
72
73 return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate,
74 SND_SOC_CLOCK_OUT);
75}
76
77static struct snd_soc_ops edb93xx_ops = {
78 .hw_params = edb93xx_hw_params,
79};
80
81static struct snd_soc_dai_link edb93xx_dai = {
82 .name = "CS4271",
83 .stream_name = "CS4271 HiFi",
84 .platform_name = "ep93xx-pcm-audio",
85 .cpu_dai_name = "ep93xx-i2s",
86 .codec_name = "spi0.0",
87 .codec_dai_name = "cs4271-hifi",
88 .ops = &edb93xx_ops,
89};
90
91static struct snd_soc_card snd_soc_edb93xx = {
92 .name = "EDB93XX",
93 .dai_link = &edb93xx_dai,
94 .num_links = 1,
95};
96
97static struct platform_device *edb93xx_snd_device;
98
99static int __init edb93xx_init(void)
100{
101 int ret;
102
103 if (!edb93xx_has_audio())
104 return -ENODEV;
105
106 ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
107 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
108 EP93XX_SYSCON_I2SCLKDIV_SPOL);
109 if (ret)
110 return ret;
111
112 edb93xx_snd_device = platform_device_alloc("soc-audio", -1);
113 if (!edb93xx_snd_device) {
114 ret = -ENOMEM;
115 goto free_i2s;
116 }
117
118 platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx);
119 ret = platform_device_add(edb93xx_snd_device);
120 if (ret)
121 goto device_put;
122
123 return 0;
124
125device_put:
126 platform_device_put(edb93xx_snd_device);
127free_i2s:
128 ep93xx_i2s_release();
129 return ret;
130}
131module_init(edb93xx_init);
132
133static void __exit edb93xx_exit(void)
134{
135 platform_device_unregister(edb93xx_snd_device);
136 ep93xx_i2s_release();
137}
138module_exit(edb93xx_exit);
139
140MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
141MODULE_DESCRIPTION("ALSA SoC EDB93xx");
142MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
new file mode 100644
index 000000000000..104e95cda0ad
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -0,0 +1,467 @@
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 switch (cmd) {
257 case SNDRV_PCM_TRIGGER_START:
258 case SNDRV_PCM_TRIGGER_RESUME:
259 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
260 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
261 /*
262 * Enable compact mode, TX slots 3 & 4, and the TX FIFO
263 * itself.
264 */
265 v |= AC97TXCR_CM;
266 v |= AC97TXCR_TX3 | AC97TXCR_TX4;
267 v |= AC97TXCR_TEN;
268 ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
269 } else {
270 /*
271 * Enable compact mode, RX slots 3 & 4, and the RX FIFO
272 * itself.
273 */
274 v |= AC97RXCR_CM;
275 v |= AC97RXCR_RX3 | AC97RXCR_RX4;
276 v |= AC97RXCR_REN;
277 ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
278 }
279 break;
280
281 case SNDRV_PCM_TRIGGER_STOP:
282 case SNDRV_PCM_TRIGGER_SUSPEND:
283 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
284 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
285 /*
286 * As per Cirrus EP93xx errata described below:
287 *
288 * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
289 *
290 * we will wait for the TX FIFO to be empty before
291 * clearing the TEN bit.
292 */
293 unsigned long timeout = jiffies + AC97_TIMEOUT;
294
295 do {
296 v = ep93xx_ac97_read_reg(info, AC97SR(1));
297 if (time_after(jiffies, timeout)) {
298 dev_warn(info->dev, "TX timeout\n");
299 break;
300 }
301 } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
302
303 /* disable the TX FIFO */
304 ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
305 } else {
306 /* disable the RX FIFO */
307 ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
308 }
309 break;
310
311 default:
312 dev_warn(info->dev, "unknown command %d\n", cmd);
313 return -EINVAL;
314 }
315
316 return 0;
317}
318
319static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
320 struct snd_soc_dai *dai)
321{
322 struct ep93xx_pcm_dma_params *dma_data;
323
324 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
325 dma_data = &ep93xx_ac97_pcm_out;
326 else
327 dma_data = &ep93xx_ac97_pcm_in;
328
329 snd_soc_dai_set_dma_data(dai, substream, dma_data);
330 return 0;
331}
332
333static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
334 .startup = ep93xx_ac97_startup,
335 .trigger = ep93xx_ac97_trigger,
336};
337
338struct snd_soc_dai_driver ep93xx_ac97_dai = {
339 .name = "ep93xx-ac97",
340 .id = 0,
341 .ac97_control = 1,
342 .playback = {
343 .stream_name = "AC97 Playback",
344 .channels_min = 2,
345 .channels_max = 2,
346 .rates = SNDRV_PCM_RATE_8000_48000,
347 .formats = SNDRV_PCM_FMTBIT_S16_LE,
348 },
349 .capture = {
350 .stream_name = "AC97 Capture",
351 .channels_min = 2,
352 .channels_max = 2,
353 .rates = SNDRV_PCM_RATE_8000_48000,
354 .formats = SNDRV_PCM_FMTBIT_S16_LE,
355 },
356 .ops = &ep93xx_ac97_dai_ops,
357};
358
359static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
360{
361 struct ep93xx_ac97_info *info;
362 int ret;
363
364 info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL);
365 if (!info)
366 return -ENOMEM;
367
368 dev_set_drvdata(&pdev->dev, info);
369
370 mutex_init(&info->lock);
371 init_completion(&info->done);
372 info->dev = &pdev->dev;
373
374 info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
375 if (!info->mem) {
376 ret = -ENXIO;
377 goto fail_free_info;
378 }
379
380 info->irq = platform_get_irq(pdev, 0);
381 if (!info->irq) {
382 ret = -ENXIO;
383 goto fail_free_info;
384 }
385
386 if (!request_mem_region(info->mem->start, resource_size(info->mem),
387 pdev->name)) {
388 ret = -EBUSY;
389 goto fail_free_info;
390 }
391
392 info->regs = ioremap(info->mem->start, resource_size(info->mem));
393 if (!info->regs) {
394 ret = -ENOMEM;
395 goto fail_release_mem;
396 }
397
398 ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH,
399 pdev->name, info);
400 if (ret)
401 goto fail_unmap_mem;
402
403 ep93xx_ac97_info = info;
404 platform_set_drvdata(pdev, info);
405
406 ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
407 if (ret)
408 goto fail_free_irq;
409
410 return 0;
411
412fail_free_irq:
413 platform_set_drvdata(pdev, NULL);
414 free_irq(info->irq, info);
415fail_unmap_mem:
416 iounmap(info->regs);
417fail_release_mem:
418 release_mem_region(info->mem->start, resource_size(info->mem));
419fail_free_info:
420 kfree(info);
421
422 return ret;
423}
424
425static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
426{
427 struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
428
429 snd_soc_unregister_dai(&pdev->dev);
430
431 /* disable the AC97 controller */
432 ep93xx_ac97_write_reg(info, AC97GCR, 0);
433
434 free_irq(info->irq, info);
435 iounmap(info->regs);
436 release_mem_region(info->mem->start, resource_size(info->mem));
437 platform_set_drvdata(pdev, NULL);
438 kfree(info);
439
440 return 0;
441}
442
443static struct platform_driver ep93xx_ac97_driver = {
444 .probe = ep93xx_ac97_probe,
445 .remove = __devexit_p(ep93xx_ac97_remove),
446 .driver = {
447 .name = "ep93xx-ac97",
448 .owner = THIS_MODULE,
449 },
450};
451
452static int __init ep93xx_ac97_init(void)
453{
454 return platform_driver_register(&ep93xx_ac97_driver);
455}
456module_init(ep93xx_ac97_init);
457
458static void __exit ep93xx_ac97_exit(void)
459{
460 platform_driver_unregister(&ep93xx_ac97_driver);
461}
462module_exit(ep93xx_ac97_exit);
463
464MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
465MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
466MODULE_LICENSE("GPL");
467MODULE_ALIAS("platform:ep93xx-ac97");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 00b946632184..042f4e93746f 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,11 +240,9 @@ 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 err;
250 246
251 switch (params_format(params)) { 247 switch (params_format(params)) {
252 case SNDRV_PCM_FORMAT_S16_LE: 248 case SNDRV_PCM_FORMAT_S16_LE:
@@ -271,21 +267,22 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
271 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); 267 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
272 268
273 /* 269 /*
274 * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values. 270 * EP93xx I2S module can be setup so SCLK / LRCLK value can be
275 * If the lrclk is pulse length is larger than the word size, then the 271 * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
276 * bit clock will be gated for the unused bits. 272 * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
273 * value is 64, because our sample size is 32 bit * 2 channels.
274 * I2S standard permits us to transmit more bits than
275 * the codec uses.
277 */ 276 */
278 div = (clk_get_rate(info->mclk) / params_rate(params)) * 277 div = clk_get_rate(info->mclk) / params_rate(params);
279 params_channels(params); 278 sdiv = 4;
280 for (sdiv = 2; sdiv <= 4; sdiv += 2) 279 if (div > (256 + 512) / 2) {
281 for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1) 280 lrdiv = 128;
282 if (sdiv * lrdiv == div) { 281 } else {
283 found = 1; 282 lrdiv = 64;
284 goto out; 283 if (div < (128 + 256) / 2)
285 } 284 sdiv = 2;
286out: 285 }
287 if (!found)
288 return -EINVAL;
289 286
290 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); 287 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
291 if (err) 288 if (err)
@@ -302,7 +299,7 @@ out:
302static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 299static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
303 unsigned int freq, int dir) 300 unsigned int freq, int dir)
304{ 301{
305 struct ep93xx_i2s_info *info = cpu_dai->private_data; 302 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
306 303
307 if (dir == SND_SOC_CLOCK_IN || clk_id != 0) 304 if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
308 return -EINVAL; 305 return -EINVAL;
@@ -313,24 +310,28 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
313#ifdef CONFIG_PM 310#ifdef CONFIG_PM
314static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) 311static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
315{ 312{
316 struct ep93xx_i2s_info *info = dai->private_data; 313 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
317 314
318 if (!dai->active) 315 if (!dai->active)
319 return; 316 return 0;
320 317
321 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); 318 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
322 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); 319 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
320
321 return 0;
323} 322}
324 323
325static int ep93xx_i2s_resume(struct snd_soc_dai *dai) 324static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
326{ 325{
327 struct ep93xx_i2s_info *info = dai->private_data; 326 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
328 327
329 if (!dai->active) 328 if (!dai->active)
330 return; 329 return 0;
331 330
332 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); 331 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
333 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); 332 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
333
334 return 0;
334} 335}
335#else 336#else
336#define ep93xx_i2s_suspend NULL 337#define ep93xx_i2s_suspend NULL
@@ -345,31 +346,26 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
345 .set_fmt = ep93xx_i2s_set_dai_fmt, 346 .set_fmt = ep93xx_i2s_set_dai_fmt,
346}; 347};
347 348
348#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 349#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
349 SNDRV_PCM_FMTBIT_S24_LE | \
350 SNDRV_PCM_FMTBIT_S32_LE)
351 350
352struct snd_soc_dai ep93xx_i2s_dai = { 351static struct snd_soc_dai_driver ep93xx_i2s_dai = {
353 .name = "ep93xx-i2s",
354 .id = 0,
355 .symmetric_rates= 1, 352 .symmetric_rates= 1,
356 .suspend = ep93xx_i2s_suspend, 353 .suspend = ep93xx_i2s_suspend,
357 .resume = ep93xx_i2s_resume, 354 .resume = ep93xx_i2s_resume,
358 .playback = { 355 .playback = {
359 .channels_min = 2, 356 .channels_min = 2,
360 .channels_max = 2, 357 .channels_max = 2,
361 .rates = SNDRV_PCM_RATE_8000_48000, 358 .rates = SNDRV_PCM_RATE_8000_192000,
362 .formats = EP93XX_I2S_FORMATS, 359 .formats = EP93XX_I2S_FORMATS,
363 }, 360 },
364 .capture = { 361 .capture = {
365 .channels_min = 2, 362 .channels_min = 2,
366 .channels_max = 2, 363 .channels_max = 2,
367 .rates = SNDRV_PCM_RATE_8000_48000, 364 .rates = SNDRV_PCM_RATE_8000_192000,
368 .formats = EP93XX_I2S_FORMATS, 365 .formats = EP93XX_I2S_FORMATS,
369 }, 366 },
370 .ops = &ep93xx_i2s_dai_ops, 367 .ops = &ep93xx_i2s_dai_ops,
371}; 368};
372EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
373 369
374static int ep93xx_i2s_probe(struct platform_device *pdev) 370static int ep93xx_i2s_probe(struct platform_device *pdev)
375{ 371{
@@ -383,8 +379,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
383 goto fail; 379 goto fail;
384 } 380 }
385 381
386 ep93xx_i2s_dai.dev = &pdev->dev; 382 dev_set_drvdata(&pdev->dev, info);
387 ep93xx_i2s_dai.private_data = info;
388 info->dma_params = ep93xx_i2s_dma_params; 383 info->dma_params = ep93xx_i2s_dma_params;
389 384
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 385 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -424,7 +419,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
424 goto fail_put_sclk; 419 goto fail_put_sclk;
425 } 420 }
426 421
427 err = snd_soc_register_dai(&ep93xx_i2s_dai); 422 err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
428 if (err) 423 if (err)
429 goto fail_put_lrclk; 424 goto fail_put_lrclk;
430 425
@@ -447,9 +442,9 @@ fail:
447 442
448static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) 443static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
449{ 444{
450 struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; 445 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
451 446
452 snd_soc_unregister_dai(&ep93xx_i2s_dai); 447 snd_soc_unregister_dai(&pdev->dev);
453 clk_put(info->lrclk); 448 clk_put(info->lrclk);
454 clk_put(info->sclk); 449 clk_put(info->sclk);
455 clk_put(info->mclk); 450 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..a456e491155f 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -35,9 +35,9 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
35 SNDRV_PCM_INFO_INTERLEAVED | 35 SNDRV_PCM_INFO_INTERLEAVED |
36 SNDRV_PCM_INFO_BLOCK_TRANSFER), 36 SNDRV_PCM_INFO_BLOCK_TRANSFER),
37 37
38 .rates = SNDRV_PCM_RATE_8000_48000, 38 .rates = SNDRV_PCM_RATE_8000_192000,
39 .rate_min = SNDRV_PCM_RATE_8000, 39 .rate_min = SNDRV_PCM_RATE_8000,
40 .rate_max = SNDRV_PCM_RATE_48000, 40 .rate_max = SNDRV_PCM_RATE_192000,
41 41
42 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 42 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
43 SNDRV_PCM_FMTBIT_S24_LE | 43 SNDRV_PCM_FMTBIT_S24_LE |
@@ -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..286817946c56
--- /dev/null
+++ b/sound/soc/ep93xx/simone.c
@@ -0,0 +1,91 @@
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 fail1;
58
59 simone_snd_device = platform_device_alloc("soc-audio", -1);
60 if (!simone_snd_device) {
61 ret = -ENOMEM;
62 goto fail2;
63 }
64
65 platform_set_drvdata(simone_snd_device, &snd_soc_simone);
66 ret = platform_device_add(simone_snd_device);
67 if (ret)
68 goto fail3;
69
70 return 0;
71
72fail3:
73 platform_device_put(simone_snd_device);
74fail2:
75 platform_device_del(simone_snd_ac97_device);
76fail1:
77 platform_device_put(simone_snd_ac97_device);
78 return ret;
79}
80module_init(simone_init);
81
82static void __exit simone_exit(void)
83{
84 platform_device_unregister(simone_snd_device);
85 platform_device_unregister(simone_snd_ac97_device);
86}
87module_exit(simone_exit);
88
89MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
90MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
91MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index 64955340ff75..dfe1d7f74ea6 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -15,14 +15,12 @@
15#include <sound/core.h> 15#include <sound/core.h>
16#include <sound/pcm.h> 16#include <sound/pcm.h>
17#include <sound/soc.h> 17#include <sound/soc.h>
18#include <sound/soc-dapm.h>
19 18
20#include <asm/mach-types.h> 19#include <asm/mach-types.h>
21#include <mach/hardware.h> 20#include <mach/hardware.h>
22 21
23#include "../codecs/tlv320aic23.h" 22#include "../codecs/tlv320aic23.h"
24#include "ep93xx-pcm.h" 23#include "ep93xx-pcm.h"
25#include "ep93xx-i2s.h"
26 24
27#define CODEC_CLOCK 5644800 25#define CODEC_CLOCK 5644800
28 26
@@ -30,8 +28,8 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream,
30 struct snd_pcm_hw_params *params) 28 struct snd_pcm_hw_params *params)
31{ 29{
32 struct snd_soc_pcm_runtime *rtd = substream->private_data; 30 struct snd_soc_pcm_runtime *rtd = substream->private_data;
33 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 31 struct snd_soc_dai *codec_dai = rtd->codec_dai;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 32 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
35 int err; 33 int err;
36 34
37 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 35 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
@@ -77,36 +75,35 @@ static const struct snd_soc_dapm_route audio_map[] = {
77 {"MICIN", NULL, "Mic Jack"}, 75 {"MICIN", NULL, "Mic Jack"},
78}; 76};
79 77
80static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) 78static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
81{ 79{
82 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 80 struct snd_soc_codec *codec = rtd->codec;
81 struct snd_soc_dapm_context *dapm = &codec->dapm;
82
83 snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
83 ARRAY_SIZE(tlv320aic23_dapm_widgets)); 84 ARRAY_SIZE(tlv320aic23_dapm_widgets));
84 85
85 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 86 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
86 return 0; 87 return 0;
87} 88}
88 89
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);