aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap')
-rw-r--r--sound/soc/omap/igep0020.c137
-rw-r--r--sound/soc/omap/mcpdm.c470
-rw-r--r--sound/soc/omap/mcpdm.h153
-rw-r--r--sound/soc/omap/omap3beagle.c149
-rw-r--r--sound/soc/omap/omap3evm.c135
-rw-r--r--sound/soc/omap/omap4-hdmi-card.c129
-rw-r--r--sound/soc/omap/overo.c139
-rw-r--r--sound/soc/omap/sdp4430.c223
8 files changed, 1535 insertions, 0 deletions
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
new file mode 100644
index 00000000000..0ae34702995
--- /dev/null
+++ b/sound/soc/omap/igep0020.c
@@ -0,0 +1,137 @@
1/*
2 * igep0020.c -- SoC audio for IGEP v2
3 *
4 * Based on sound/soc/omap/overo.c by Steve Sakoman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27
28#include <asm/mach-types.h>
29#include <mach/hardware.h>
30#include <mach/gpio.h>
31#include <plat/mcbsp.h>
32
33#include "omap-mcbsp.h"
34#include "omap-pcm.h"
35
36static int igep2_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params)
38{
39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 int ret;
43
44 /* Set codec DAI configuration */
45 ret = snd_soc_dai_set_fmt(codec_dai,
46 SND_SOC_DAIFMT_I2S |
47 SND_SOC_DAIFMT_NB_NF |
48 SND_SOC_DAIFMT_CBM_CFM);
49 if (ret < 0) {
50 printk(KERN_ERR "can't set codec DAI configuration\n");
51 return ret;
52 }
53
54 /* Set cpu DAI configuration */
55 ret = snd_soc_dai_set_fmt(cpu_dai,
56 SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_NF |
58 SND_SOC_DAIFMT_CBM_CFM);
59 if (ret < 0) {
60 printk(KERN_ERR "can't set cpu DAI configuration\n");
61 return ret;
62 }
63
64 /* Set the codec system clock for DAC and ADC */
65 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
66 SND_SOC_CLOCK_IN);
67 if (ret < 0) {
68 printk(KERN_ERR "can't set codec system clock\n");
69 return ret;
70 }
71
72 return 0;
73}
74
75static struct snd_soc_ops igep2_ops = {
76 .hw_params = igep2_hw_params,
77};
78
79/* Digital audio interface glue - connects codec <--> CPU */
80static struct snd_soc_dai_link igep2_dai = {
81 .name = "TWL4030",
82 .stream_name = "TWL4030",
83 .cpu_dai_name = "omap-mcbsp-dai.1",
84 .codec_dai_name = "twl4030-hifi",
85 .platform_name = "omap-pcm-audio",
86 .codec_name = "twl4030-codec",
87 .ops = &igep2_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_igep2 = {
92 .name = "igep2",
93 .dai_link = &igep2_dai,
94 .num_links = 1,
95};
96
97static struct platform_device *igep2_snd_device;
98
99static int __init igep2_soc_init(void)
100{
101 int ret;
102
103 if (!machine_is_igep0020())
104 return -ENODEV;
105 printk(KERN_INFO "IGEP v2 SoC init\n");
106
107 igep2_snd_device = platform_device_alloc("soc-audio", -1);
108 if (!igep2_snd_device) {
109 printk(KERN_ERR "Platform device allocation failed\n");
110 return -ENOMEM;
111 }
112
113 platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);
114
115 ret = platform_device_add(igep2_snd_device);
116 if (ret)
117 goto err1;
118
119 return 0;
120
121err1:
122 printk(KERN_ERR "Unable to add platform device\n");
123 platform_device_put(igep2_snd_device);
124
125 return ret;
126}
127module_init(igep2_soc_init);
128
129static void __exit igep2_soc_exit(void)
130{
131 platform_device_unregister(igep2_snd_device);
132}
133module_exit(igep2_soc_exit);
134
135MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>");
136MODULE_DESCRIPTION("ALSA SoC IGEP v2");
137MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
new file mode 100644
index 00000000000..50e59194ad8
--- /dev/null
+++ b/sound/soc/omap/mcpdm.c
@@ -0,0 +1,470 @@
1/*
2 * mcpdm.c -- McPDM interface driver
3 *
4 * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
5 * Copyright (C) 2009 - Texas Instruments, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/device.h>
26#include <linux/platform_device.h>
27#include <linux/wait.h>
28#include <linux/slab.h>
29#include <linux/interrupt.h>
30#include <linux/err.h>
31#include <linux/clk.h>
32#include <linux/delay.h>
33#include <linux/io.h>
34#include <linux/irq.h>
35
36#include "mcpdm.h"
37
38static struct omap_mcpdm *mcpdm;
39
40static inline void omap_mcpdm_write(u16 reg, u32 val)
41{
42 __raw_writel(val, mcpdm->io_base + reg);
43}
44
45static inline int omap_mcpdm_read(u16 reg)
46{
47 return __raw_readl(mcpdm->io_base + reg);
48}
49
50static void omap_mcpdm_reg_dump(void)
51{
52 dev_dbg(mcpdm->dev, "***********************\n");
53 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
54 omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
55 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
56 omap_mcpdm_read(MCPDM_IRQSTATUS));
57 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
58 omap_mcpdm_read(MCPDM_IRQENABLE_SET));
59 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
60 omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
61 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
62 omap_mcpdm_read(MCPDM_IRQWAKE_EN));
63 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
64 omap_mcpdm_read(MCPDM_DMAENABLE_SET));
65 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
66 omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
67 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
68 omap_mcpdm_read(MCPDM_DMAWAKEEN));
69 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
70 omap_mcpdm_read(MCPDM_CTRL));
71 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
72 omap_mcpdm_read(MCPDM_DN_DATA));
73 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
74 omap_mcpdm_read(MCPDM_UP_DATA));
75 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
76 omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
77 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
78 omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
79 dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
80 omap_mcpdm_read(MCPDM_DN_OFFSET));
81 dev_dbg(mcpdm->dev, "***********************\n");
82}
83
84/*
85 * Takes the McPDM module in and out of reset state.
86 * Uplink and downlink can be reset individually.
87 */
88static void omap_mcpdm_reset_capture(int reset)
89{
90 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
91
92 if (reset)
93 ctrl |= SW_UP_RST;
94 else
95 ctrl &= ~SW_UP_RST;
96
97 omap_mcpdm_write(MCPDM_CTRL, ctrl);
98}
99
100static void omap_mcpdm_reset_playback(int reset)
101{
102 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
103
104 if (reset)
105 ctrl |= SW_DN_RST;
106 else
107 ctrl &= ~SW_DN_RST;
108
109 omap_mcpdm_write(MCPDM_CTRL, ctrl);
110}
111
112/*
113 * Enables the transfer through the PDM interface to/from the Phoenix
114 * codec by enabling the corresponding UP or DN channels.
115 */
116void omap_mcpdm_start(int stream)
117{
118 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
119
120 if (stream)
121 ctrl |= mcpdm->up_channels;
122 else
123 ctrl |= mcpdm->dn_channels;
124
125 omap_mcpdm_write(MCPDM_CTRL, ctrl);
126}
127
128/*
129 * Disables the transfer through the PDM interface to/from the Phoenix
130 * codec by disabling the corresponding UP or DN channels.
131 */
132void omap_mcpdm_stop(int stream)
133{
134 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
135
136 if (stream)
137 ctrl &= ~mcpdm->up_channels;
138 else
139 ctrl &= ~mcpdm->dn_channels;
140
141 omap_mcpdm_write(MCPDM_CTRL, ctrl);
142}
143
144/*
145 * Configures McPDM uplink for audio recording.
146 * This function should be called before omap_mcpdm_start.
147 */
148int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
149{
150 int irq_mask = 0;
151 int ctrl;
152
153 if (!uplink)
154 return -EINVAL;
155
156 mcpdm->uplink = uplink;
157
158 /* Enable irq request generation */
159 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
160 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
161
162 /* Configure uplink threshold */
163 if (uplink->threshold > UP_THRES_MAX)
164 uplink->threshold = UP_THRES_MAX;
165
166 omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
167
168 /* Configure DMA controller */
169 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
170
171 /* Set pdm out format */
172 ctrl = omap_mcpdm_read(MCPDM_CTRL);
173 ctrl &= ~PDMOUTFORMAT;
174 ctrl |= uplink->format & PDMOUTFORMAT;
175
176 /* Uplink channels */
177 mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
178
179 omap_mcpdm_write(MCPDM_CTRL, ctrl);
180
181 return 0;
182}
183
184/*
185 * Configures McPDM downlink for audio playback.
186 * This function should be called before omap_mcpdm_start.
187 */
188int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
189{
190 int irq_mask = 0;
191 int ctrl;
192
193 if (!downlink)
194 return -EINVAL;
195
196 mcpdm->downlink = downlink;
197
198 /* Enable irq request generation */
199 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
200 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
201
202 /* Configure uplink threshold */
203 if (downlink->threshold > DN_THRES_MAX)
204 downlink->threshold = DN_THRES_MAX;
205
206 omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
207
208 /* Enable DMA request generation */
209 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
210
211 /* Set pdm out format */
212 ctrl = omap_mcpdm_read(MCPDM_CTRL);
213 ctrl &= ~PDMOUTFORMAT;
214 ctrl |= downlink->format & PDMOUTFORMAT;
215
216 /* Downlink channels */
217 mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
218
219 omap_mcpdm_write(MCPDM_CTRL, ctrl);
220
221 return 0;
222}
223
224/*
225 * Cleans McPDM uplink configuration.
226 * This function should be called when the stream is closed.
227 */
228int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
229{
230 int irq_mask = 0;
231
232 if (!uplink)
233 return -EINVAL;
234
235 /* Disable irq request generation */
236 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
237 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
238
239 /* Disable DMA request generation */
240 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
241
242 /* Clear Downlink channels */
243 mcpdm->up_channels = 0;
244
245 mcpdm->uplink = NULL;
246
247 return 0;
248}
249
250/*
251 * Cleans McPDM downlink configuration.
252 * This function should be called when the stream is closed.
253 */
254int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
255{
256 int irq_mask = 0;
257
258 if (!downlink)
259 return -EINVAL;
260
261 /* Disable irq request generation */
262 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
263 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
264
265 /* Disable DMA request generation */
266 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
267
268 /* clear Downlink channels */
269 mcpdm->dn_channels = 0;
270
271 mcpdm->downlink = NULL;
272
273 return 0;
274}
275
276static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
277{
278 struct omap_mcpdm *mcpdm_irq = dev_id;
279 int irq_status;
280
281 irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
282
283 /* Acknowledge irq event */
284 omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
285
286 if (irq & MCPDM_DN_IRQ_FULL) {
287 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
288 omap_mcpdm_reset_playback(1);
289 omap_mcpdm_playback_open(mcpdm_irq->downlink);
290 omap_mcpdm_reset_playback(0);
291 }
292
293 if (irq & MCPDM_DN_IRQ_EMPTY) {
294 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
295 omap_mcpdm_reset_playback(1);
296 omap_mcpdm_playback_open(mcpdm_irq->downlink);
297 omap_mcpdm_reset_playback(0);
298 }
299
300 if (irq & MCPDM_DN_IRQ) {
301 dev_dbg(mcpdm_irq->dev, "DN write request\n");
302 }
303
304 if (irq & MCPDM_UP_IRQ_FULL) {
305 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
306 omap_mcpdm_reset_capture(1);
307 omap_mcpdm_capture_open(mcpdm_irq->uplink);
308 omap_mcpdm_reset_capture(0);
309 }
310
311 if (irq & MCPDM_UP_IRQ_EMPTY) {
312 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
313 omap_mcpdm_reset_capture(1);
314 omap_mcpdm_capture_open(mcpdm_irq->uplink);
315 omap_mcpdm_reset_capture(0);
316 }
317
318 if (irq & MCPDM_UP_IRQ) {
319 dev_dbg(mcpdm_irq->dev, "UP write request\n");
320 }
321
322 return IRQ_HANDLED;
323}
324
325int omap_mcpdm_request(void)
326{
327 int ret;
328
329 clk_enable(mcpdm->clk);
330
331 spin_lock(&mcpdm->lock);
332
333 if (!mcpdm->free) {
334 dev_err(mcpdm->dev, "McPDM interface is in use\n");
335 spin_unlock(&mcpdm->lock);
336 ret = -EBUSY;
337 goto err;
338 }
339 mcpdm->free = 0;
340
341 spin_unlock(&mcpdm->lock);
342
343 /* Disable lines while request is ongoing */
344 omap_mcpdm_write(MCPDM_CTRL, 0x00);
345
346 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
347 0, "McPDM", (void *)mcpdm);
348 if (ret) {
349 dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
350 goto err;
351 }
352
353 return 0;
354
355err:
356 clk_disable(mcpdm->clk);
357 return ret;
358}
359
360void omap_mcpdm_free(void)
361{
362 spin_lock(&mcpdm->lock);
363 if (mcpdm->free) {
364 dev_err(mcpdm->dev, "McPDM interface is already free\n");
365 spin_unlock(&mcpdm->lock);
366 return;
367 }
368 mcpdm->free = 1;
369 spin_unlock(&mcpdm->lock);
370
371 clk_disable(mcpdm->clk);
372
373 free_irq(mcpdm->irq, (void *)mcpdm);
374}
375
376/* Enable/disable DC offset cancelation for the analog
377 * headset path (PDM channels 1 and 2).
378 */
379int omap_mcpdm_set_offset(int offset1, int offset2)
380{
381 int offset;
382
383 if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
384 return -EINVAL;
385
386 offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
387
388 /* offset cancellation for channel 1 */
389 if (offset1)
390 offset |= DN_OFST_RX1_EN;
391 else
392 offset &= ~DN_OFST_RX1_EN;
393
394 /* offset cancellation for channel 2 */
395 if (offset2)
396 offset |= DN_OFST_RX2_EN;
397 else
398 offset &= ~DN_OFST_RX2_EN;
399
400 omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
401
402 return 0;
403}
404
405int __devinit omap_mcpdm_probe(struct platform_device *pdev)
406{
407 struct resource *res;
408 int ret = 0;
409
410 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
411 if (!mcpdm) {
412 ret = -ENOMEM;
413 goto exit;
414 }
415
416 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
417 if (res == NULL) {
418 dev_err(&pdev->dev, "no resource\n");
419 goto err_resource;
420 }
421
422 spin_lock_init(&mcpdm->lock);
423 mcpdm->free = 1;
424 mcpdm->io_base = ioremap(res->start, resource_size(res));
425 if (!mcpdm->io_base) {
426 ret = -ENOMEM;
427 goto err_resource;
428 }
429
430 mcpdm->irq = platform_get_irq(pdev, 0);
431
432 mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
433 if (IS_ERR(mcpdm->clk)) {
434 ret = PTR_ERR(mcpdm->clk);
435 dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
436 goto err_clk;
437 }
438
439 mcpdm->dev = &pdev->dev;
440 platform_set_drvdata(pdev, mcpdm);
441
442 return 0;
443
444err_clk:
445 iounmap(mcpdm->io_base);
446err_resource:
447 kfree(mcpdm);
448exit:
449 return ret;
450}
451
452int omap_mcpdm_remove(struct platform_device *pdev)
453{
454 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
455
456 platform_set_drvdata(pdev, NULL);
457
458 clk_put(mcpdm_ptr->clk);
459
460 iounmap(mcpdm_ptr->io_base);
461
462 mcpdm_ptr->clk = NULL;
463 mcpdm_ptr->free = 0;
464 mcpdm_ptr->dev = NULL;
465
466 kfree(mcpdm_ptr);
467
468 return 0;
469}
470
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
new file mode 100644
index 00000000000..20c20a8649f
--- /dev/null
+++ b/sound/soc/omap/mcpdm.h
@@ -0,0 +1,153 @@
1/*
2 * mcpdm.h -- Defines for McPDM driver
3 *
4 * Author: Jorge Eduardo Candelaria <x0107209@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/* McPDM registers */
23
24#define MCPDM_REVISION 0x00
25#define MCPDM_SYSCONFIG 0x10
26#define MCPDM_IRQSTATUS_RAW 0x24
27#define MCPDM_IRQSTATUS 0x28
28#define MCPDM_IRQENABLE_SET 0x2C
29#define MCPDM_IRQENABLE_CLR 0x30
30#define MCPDM_IRQWAKE_EN 0x34
31#define MCPDM_DMAENABLE_SET 0x38
32#define MCPDM_DMAENABLE_CLR 0x3C
33#define MCPDM_DMAWAKEEN 0x40
34#define MCPDM_CTRL 0x44
35#define MCPDM_DN_DATA 0x48
36#define MCPDM_UP_DATA 0x4C
37#define MCPDM_FIFO_CTRL_DN 0x50
38#define MCPDM_FIFO_CTRL_UP 0x54
39#define MCPDM_DN_OFFSET 0x58
40
41/*
42 * MCPDM_IRQ bit fields
43 * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
44 */
45
46#define MCPDM_DN_IRQ (1 << 0)
47#define MCPDM_DN_IRQ_EMPTY (1 << 1)
48#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2)
49#define MCPDM_DN_IRQ_FULL (1 << 3)
50
51#define MCPDM_UP_IRQ (1 << 8)
52#define MCPDM_UP_IRQ_EMPTY (1 << 9)
53#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10)
54#define MCPDM_UP_IRQ_FULL (1 << 11)
55
56#define MCPDM_DOWNLINK_IRQ_MASK 0x00F
57#define MCPDM_UPLINK_IRQ_MASK 0xF00
58
59/*
60 * MCPDM_DMAENABLE bit fields
61 */
62
63#define DMA_DN_ENABLE 0x1
64#define DMA_UP_ENABLE 0x2
65
66/*
67 * MCPDM_CTRL bit fields
68 */
69
70#define PDM_UP1_EN 0x0001
71#define PDM_UP2_EN 0x0002
72#define PDM_UP3_EN 0x0004
73#define PDM_DN1_EN 0x0008
74#define PDM_DN2_EN 0x0010
75#define PDM_DN3_EN 0x0020
76#define PDM_DN4_EN 0x0040
77#define PDM_DN5_EN 0x0080
78#define PDMOUTFORMAT 0x0100
79#define CMD_INT 0x0200
80#define STATUS_INT 0x0400
81#define SW_UP_RST 0x0800
82#define SW_DN_RST 0x1000
83#define PDM_UP_MASK 0x007
84#define PDM_DN_MASK 0x0F8
85#define PDM_CMD_MASK 0x200
86#define PDM_STATUS_MASK 0x400
87
88
89#define PDMOUTFORMAT_LJUST (0 << 8)
90#define PDMOUTFORMAT_RJUST (1 << 8)
91
92/*
93 * MCPDM_FIFO_CTRL bit fields
94 */
95
96#define UP_THRES_MAX 0xF
97#define DN_THRES_MAX 0xF
98
99/*
100 * MCPDM_DN_OFFSET bit fields
101 */
102
103#define DN_OFST_RX1_EN 0x0001
104#define DN_OFST_RX2_EN 0x0100
105
106#define DN_OFST_RX1 1
107#define DN_OFST_RX2 9
108#define DN_OFST_MAX 0x1F
109
110#define MCPDM_UPLINK 1
111#define MCPDM_DOWNLINK 2
112
113struct omap_mcpdm_link {
114 int irq_mask;
115 int threshold;
116 int format;
117 int channels;
118};
119
120struct omap_mcpdm_platform_data {
121 unsigned long phys_base;
122 u16 irq;
123};
124
125struct omap_mcpdm {
126 struct device *dev;
127 unsigned long phys_base;
128 void __iomem *io_base;
129 u8 free;
130 int irq;
131
132 spinlock_t lock;
133 struct omap_mcpdm_platform_data *pdata;
134 struct clk *clk;
135 struct omap_mcpdm_link *downlink;
136 struct omap_mcpdm_link *uplink;
137 struct completion irq_completion;
138
139 int dn_channels;
140 int up_channels;
141};
142
143extern void omap_mcpdm_start(int stream);
144extern void omap_mcpdm_stop(int stream);
145extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
146extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
147extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
148extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
149extern int omap_mcpdm_request(void);
150extern void omap_mcpdm_free(void);
151extern int omap_mcpdm_set_offset(int offset1, int offset2);
152int __devinit omap_mcpdm_probe(struct platform_device *pdev);
153int omap_mcpdm_remove(struct platform_device *pdev);
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
new file mode 100644
index 00000000000..40db813c079
--- /dev/null
+++ b/sound/soc/omap/omap3beagle.c
@@ -0,0 +1,149 @@
1/*
2 * omap3beagle.c -- SoC audio for OMAP3 Beagle
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27
28#include <asm/mach-types.h>
29#include <mach/hardware.h>
30#include <mach/gpio.h>
31#include <plat/mcbsp.h>
32
33#include "omap-mcbsp.h"
34#include "omap-pcm.h"
35
36static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params)
38{
39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 unsigned int fmt;
43 int ret;
44
45 switch (params_channels(params)) {
46 case 2: /* Stereo I2S mode */
47 fmt = SND_SOC_DAIFMT_I2S |
48 SND_SOC_DAIFMT_NB_NF |
49 SND_SOC_DAIFMT_CBM_CFM;
50 break;
51 case 4: /* Four channel TDM mode */
52 fmt = SND_SOC_DAIFMT_DSP_A |
53 SND_SOC_DAIFMT_IB_NF |
54 SND_SOC_DAIFMT_CBM_CFM;
55 break;
56 default:
57 return -EINVAL;
58 }
59
60 /* Set codec DAI configuration */
61 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
62 if (ret < 0) {
63 printk(KERN_ERR "can't set codec DAI configuration\n");
64 return ret;
65 }
66
67 /* Set cpu DAI configuration */
68 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
69 if (ret < 0) {
70 printk(KERN_ERR "can't set cpu DAI configuration\n");
71 return ret;
72 }
73
74 /* Set the codec system clock for DAC and ADC */
75 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
76 SND_SOC_CLOCK_IN);
77 if (ret < 0) {
78 printk(KERN_ERR "can't set codec system clock\n");
79 return ret;
80 }
81
82 return 0;
83}
84
85static struct snd_soc_ops omap3beagle_ops = {
86 .hw_params = omap3beagle_hw_params,
87};
88
89/* Digital audio interface glue - connects codec <--> CPU */
90static struct snd_soc_dai_link omap3beagle_dai = {
91 .name = "TWL4030",
92 .stream_name = "TWL4030",
93 .cpu_dai_name = "omap-mcbsp-dai.1",
94 .platform_name = "omap-pcm-audio",
95 .codec_dai_name = "twl4030-hifi",
96 .codec_name = "twl4030-codec",
97 .ops = &omap3beagle_ops,
98};
99
100/* Audio machine driver */
101static struct snd_soc_card snd_soc_omap3beagle = {
102 .name = "omap3beagle",
103 .owner = THIS_MODULE,
104 .dai_link = &omap3beagle_dai,
105 .num_links = 1,
106};
107
108static struct platform_device *omap3beagle_snd_device;
109
110static int __init omap3beagle_soc_init(void)
111{
112 int ret;
113
114 if (!(machine_is_omap3_beagle() || machine_is_devkit8000()))
115 return -ENODEV;
116 pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");
117
118 omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
119 if (!omap3beagle_snd_device) {
120 printk(KERN_ERR "Platform device allocation failed\n");
121 return -ENOMEM;
122 }
123
124 platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);
125
126 ret = platform_device_add(omap3beagle_snd_device);
127 if (ret)
128 goto err1;
129
130 return 0;
131
132err1:
133 printk(KERN_ERR "Unable to add platform device\n");
134 platform_device_put(omap3beagle_snd_device);
135
136 return ret;
137}
138
139static void __exit omap3beagle_soc_exit(void)
140{
141 platform_device_unregister(omap3beagle_snd_device);
142}
143
144module_init(omap3beagle_soc_init);
145module_exit(omap3beagle_soc_exit);
146
147MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
148MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
149MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
new file mode 100644
index 00000000000..0daa0446983
--- /dev/null
+++ b/sound/soc/omap/omap3evm.c
@@ -0,0 +1,135 @@
1/*
2 * omap3evm.c -- ALSA SoC support for OMAP3 EVM
3 *
4 * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
5 *
6 * Based on sound/soc/omap/beagle.c by Steve Sakoman
7 *
8 * Copyright (C) 2008 Texas Instruments, Incorporated
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
15 * whether express or implied; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25
26#include <asm/mach-types.h>
27#include <mach/hardware.h>
28#include <mach/gpio.h>
29#include <plat/mcbsp.h>
30
31#include "omap-mcbsp.h"
32#include "omap-pcm.h"
33
34static int omap3evm_hw_params(struct snd_pcm_substream *substream,
35 struct snd_pcm_hw_params *params)
36{
37 struct snd_soc_pcm_runtime *rtd = substream->private_data;
38 struct snd_soc_dai *codec_dai = rtd->codec_dai;
39 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
40 int ret;
41
42 /* Set codec DAI configuration */
43 ret = snd_soc_dai_set_fmt(codec_dai,
44 SND_SOC_DAIFMT_I2S |
45 SND_SOC_DAIFMT_NB_NF |
46 SND_SOC_DAIFMT_CBM_CFM);
47 if (ret < 0) {
48 printk(KERN_ERR "Can't set codec DAI configuration\n");
49 return ret;
50 }
51
52 /* Set cpu DAI configuration */
53 ret = snd_soc_dai_set_fmt(cpu_dai,
54 SND_SOC_DAIFMT_I2S |
55 SND_SOC_DAIFMT_NB_NF |
56 SND_SOC_DAIFMT_CBM_CFM);
57 if (ret < 0) {
58 printk(KERN_ERR "Can't set cpu DAI configuration\n");
59 return ret;
60 }
61
62 /* Set the codec system clock for DAC and ADC */
63 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
64 SND_SOC_CLOCK_IN);
65 if (ret < 0) {
66 printk(KERN_ERR "Can't set codec system clock\n");
67 return ret;
68 }
69
70 return 0;
71}
72
73static struct snd_soc_ops omap3evm_ops = {
74 .hw_params = omap3evm_hw_params,
75};
76
77/* Digital audio interface glue - connects codec <--> CPU */
78static struct snd_soc_dai_link omap3evm_dai = {
79 .name = "TWL4030",
80 .stream_name = "TWL4030",
81 .cpu_dai_name = "omap-mcbsp-dai.1",
82 .codec_dai_name = "twl4030-hifi",
83 .platform_name = "omap-pcm-audio",
84 .codec_name = "twl4030-codec",
85 .ops = &omap3evm_ops,
86};
87
88/* Audio machine driver */
89static struct snd_soc_card snd_soc_omap3evm = {
90 .name = "omap3evm",
91 .dai_link = &omap3evm_dai,
92 .num_links = 1,
93};
94
95static struct platform_device *omap3evm_snd_device;
96
97static int __init omap3evm_soc_init(void)
98{
99 int ret;
100
101 if (!machine_is_omap3evm())
102 return -ENODEV;
103 pr_info("OMAP3 EVM SoC init\n");
104
105 omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
106 if (!omap3evm_snd_device) {
107 printk(KERN_ERR "Platform device allocation failed\n");
108 return -ENOMEM;
109 }
110
111 platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);
112 ret = platform_device_add(omap3evm_snd_device);
113 if (ret)
114 goto err1;
115
116 return 0;
117
118err1:
119 printk(KERN_ERR "Unable to add platform device\n");
120 platform_device_put(omap3evm_snd_device);
121
122 return ret;
123}
124
125static void __exit omap3evm_soc_exit(void)
126{
127 platform_device_unregister(omap3evm_snd_device);
128}
129
130module_init(omap3evm_soc_init);
131module_exit(omap3evm_soc_exit);
132
133MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
134MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
135MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
new file mode 100644
index 00000000000..9f32615b81f
--- /dev/null
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -0,0 +1,129 @@
1/*
2 * omap4-hdmi-card.c
3 *
4 * OMAP ALSA SoC machine driver for TI OMAP4 HDMI
5 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Author: Ricardo Neri <ricardo.neri@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <sound/pcm.h>
25#include <sound/soc.h>
26#include <asm/mach-types.h>
27#include <video/omapdss.h>
28
29#define DRV_NAME "omap4-hdmi-audio"
30
31static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
32 struct snd_pcm_hw_params *params)
33{
34 int i;
35 struct omap_overlay_manager *mgr = NULL;
36 struct device *dev = substream->pcm->card->dev;
37
38 /* Find DSS HDMI device */
39 for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
40 mgr = omap_dss_get_overlay_manager(i);
41 if (mgr && mgr->device
42 && mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
43 break;
44 }
45
46 if (i == omap_dss_get_num_overlay_managers()) {
47 dev_err(dev, "HDMI display device not found!\n");
48 return -ENODEV;
49 }
50
51 /* Make sure HDMI is power-on to avoid L3 interconnect errors */
52 if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
53 dev_err(dev, "HDMI display is not active!\n");
54 return -EIO;
55 }
56
57 return 0;
58}
59
60static struct snd_soc_ops omap4_hdmi_dai_ops = {
61 .hw_params = omap4_hdmi_dai_hw_params,
62};
63
64static struct snd_soc_dai_link omap4_hdmi_dai = {
65 .name = "HDMI",
66 .stream_name = "HDMI",
67 .cpu_dai_name = "hdmi-audio-dai",
68 .platform_name = "omap-pcm-audio",
69 .codec_name = "omapdss_hdmi",
70 .codec_dai_name = "hdmi-audio-codec",
71 .ops = &omap4_hdmi_dai_ops,
72};
73
74static struct snd_soc_card snd_soc_omap4_hdmi = {
75 .name = "OMAP4HDMI",
76 .dai_link = &omap4_hdmi_dai,
77 .num_links = 1,
78};
79
80static __devinit int omap4_hdmi_probe(struct platform_device *pdev)
81{
82 struct snd_soc_card *card = &snd_soc_omap4_hdmi;
83 int ret;
84
85 card->dev = &pdev->dev;
86
87 ret = snd_soc_register_card(card);
88 if (ret) {
89 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
90 card->dev = NULL;
91 return ret;
92 }
93 return 0;
94}
95
96static int __devexit omap4_hdmi_remove(struct platform_device *pdev)
97{
98 struct snd_soc_card *card = platform_get_drvdata(pdev);
99
100 snd_soc_unregister_card(card);
101 card->dev = NULL;
102 return 0;
103}
104
105static struct platform_driver omap4_hdmi_driver = {
106 .driver = {
107 .name = "omap4-hdmi-audio",
108 .owner = THIS_MODULE,
109 },
110 .probe = omap4_hdmi_probe,
111 .remove = __devexit_p(omap4_hdmi_remove),
112};
113
114static int __init omap4_hdmi_init(void)
115{
116 return platform_driver_register(&omap4_hdmi_driver);
117}
118module_init(omap4_hdmi_init);
119
120static void __exit omap4_hdmi_exit(void)
121{
122 platform_driver_unregister(&omap4_hdmi_driver);
123}
124module_exit(omap4_hdmi_exit);
125
126MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
127MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
128MODULE_LICENSE("GPL");
129MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
new file mode 100644
index 00000000000..bbcf380bfb5
--- /dev/null
+++ b/sound/soc/omap/overo.c
@@ -0,0 +1,139 @@
1/*
2 * overo.c -- SoC audio for Gumstix Overo
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27
28#include <asm/mach-types.h>
29#include <mach/hardware.h>
30#include <mach/gpio.h>
31#include <plat/mcbsp.h>
32
33#include "omap-mcbsp.h"
34#include "omap-pcm.h"
35
36static int overo_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params)
38{
39 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 int ret;
43
44 /* Set codec DAI configuration */
45 ret = snd_soc_dai_set_fmt(codec_dai,
46 SND_SOC_DAIFMT_I2S |
47 SND_SOC_DAIFMT_NB_NF |
48 SND_SOC_DAIFMT_CBM_CFM);
49 if (ret < 0) {
50 printk(KERN_ERR "can't set codec DAI configuration\n");
51 return ret;
52 }
53
54 /* Set cpu DAI configuration */
55 ret = snd_soc_dai_set_fmt(cpu_dai,
56 SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_NF |
58 SND_SOC_DAIFMT_CBM_CFM);
59 if (ret < 0) {
60 printk(KERN_ERR "can't set cpu DAI configuration\n");
61 return ret;
62 }
63
64 /* Set the codec system clock for DAC and ADC */
65 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
66 SND_SOC_CLOCK_IN);
67 if (ret < 0) {
68 printk(KERN_ERR "can't set codec system clock\n");
69 return ret;
70 }
71
72 return 0;
73}
74
75static struct snd_soc_ops overo_ops = {
76 .hw_params = overo_hw_params,
77};
78
79/* Digital audio interface glue - connects codec <--> CPU */
80static struct snd_soc_dai_link overo_dai = {
81 .name = "TWL4030",
82 .stream_name = "TWL4030",
83 .cpu_dai_name = "omap-mcbsp-dai.1",
84 .codec_dai_name = "twl4030-hifi",
85 .platform_name = "omap-pcm-audio",
86 .codec_name = "twl4030-codec",
87 .ops = &overo_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_overo = {
92 .name = "overo",
93 .dai_link = &overo_dai,
94 .num_links = 1,
95};
96
97static struct platform_device *overo_snd_device;
98
99static int __init overo_soc_init(void)
100{
101 int ret;
102
103 if (!(machine_is_overo() || machine_is_cm_t35())) {
104 pr_debug("Incomatible machine!\n");
105 return -ENODEV;
106 }
107 printk(KERN_INFO "overo SoC init\n");
108
109 overo_snd_device = platform_device_alloc("soc-audio", -1);
110 if (!overo_snd_device) {
111 printk(KERN_ERR "Platform device allocation failed\n");
112 return -ENOMEM;
113 }
114
115 platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);
116
117 ret = platform_device_add(overo_snd_device);
118 if (ret)
119 goto err1;
120
121 return 0;
122
123err1:
124 printk(KERN_ERR "Unable to add platform device\n");
125 platform_device_put(overo_snd_device);
126
127 return ret;
128}
129module_init(overo_soc_init);
130
131static void __exit overo_soc_exit(void)
132{
133 platform_device_unregister(overo_snd_device);
134}
135module_exit(overo_soc_exit);
136
137MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
138MODULE_DESCRIPTION("ALSA SoC overo");
139MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
new file mode 100644
index 00000000000..b80efb02bfc
--- /dev/null
+++ b/sound/soc/omap/sdp4430.c
@@ -0,0 +1,223 @@
1/*
2 * sdp4430.c -- SoC audio for TI OMAP4430 SDP
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <linux/mfd/twl6040.h>
25
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/jack.h>
30
31#include <asm/mach-types.h>
32#include <plat/hardware.h>
33#include <plat/mux.h>
34
35#include "mcpdm.h"
36#include "omap-pcm.h"
37#include "../codecs/twl6040.h"
38
39static int sdp4430_hw_params(struct snd_pcm_substream *substream,
40 struct snd_pcm_hw_params *params)
41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
44 int clk_id, freq;
45 int ret;
46
47 clk_id = twl6040_get_clk_id(rtd->codec);
48 if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
49 freq = 38400000;
50 else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
51 freq = 32768;
52 else
53 return -EINVAL;
54
55 /* set the codec mclk */
56 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
57 SND_SOC_CLOCK_IN);
58 if (ret) {
59 printk(KERN_ERR "can't set codec system clock\n");
60 return ret;
61 }
62 return ret;
63}
64
65static struct snd_soc_ops sdp4430_ops = {
66 .hw_params = sdp4430_hw_params,
67};
68
69/* Headset jack */
70static struct snd_soc_jack hs_jack;
71
72/*Headset jack detection DAPM pins */
73static struct snd_soc_jack_pin hs_jack_pins[] = {
74 {
75 .pin = "Headset Mic",
76 .mask = SND_JACK_MICROPHONE,
77 },
78 {
79 .pin = "Headset Stereophone",
80 .mask = SND_JACK_HEADPHONE,
81 },
82};
83
84/* SDP4430 machine DAPM */
85static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
86 SND_SOC_DAPM_MIC("Ext Mic", NULL),
87 SND_SOC_DAPM_SPK("Ext Spk", NULL),
88 SND_SOC_DAPM_MIC("Headset Mic", NULL),
89 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
90 SND_SOC_DAPM_SPK("Earphone Spk", NULL),
91 SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
92};
93
94static const struct snd_soc_dapm_route audio_map[] = {
95 /* External Mics: MAINMIC, SUBMIC with bias*/
96 {"MAINMIC", NULL, "Main Mic Bias"},
97 {"SUBMIC", NULL, "Main Mic Bias"},
98 {"Main Mic Bias", NULL, "Ext Mic"},
99
100 /* External Speakers: HFL, HFR */
101 {"Ext Spk", NULL, "HFL"},
102 {"Ext Spk", NULL, "HFR"},
103
104 /* Headset Mic: HSMIC with bias */
105 {"HSMIC", NULL, "Headset Mic Bias"},
106 {"Headset Mic Bias", NULL, "Headset Mic"},
107
108 /* Headset Stereophone (Headphone): HSOL, HSOR */
109 {"Headset Stereophone", NULL, "HSOL"},
110 {"Headset Stereophone", NULL, "HSOR"},
111
112 /* Earphone speaker */
113 {"Earphone Spk", NULL, "EP"},
114
115 /* Aux/FM Stereo In: AFML, AFMR */
116 {"AFML", NULL, "Aux/FM Stereo In"},
117 {"AFMR", NULL, "Aux/FM Stereo In"},
118};
119
120static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
121{
122 struct snd_soc_codec *codec = rtd->codec;
123 struct snd_soc_dapm_context *dapm = &codec->dapm;
124 int ret;
125
126 /* Add SDP4430 specific widgets */
127 ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
128 ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
129 if (ret)
130 return ret;
131
132 /* Set up SDP4430 specific audio path audio_map */
133 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
134
135 /* SDP4430 connected pins */
136 snd_soc_dapm_enable_pin(dapm, "Ext Mic");
137 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
138 snd_soc_dapm_enable_pin(dapm, "AFML");
139 snd_soc_dapm_enable_pin(dapm, "AFMR");
140 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
141 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
142
143 ret = snd_soc_dapm_sync(dapm);
144 if (ret)
145 return ret;
146
147 /* Headset jack detection */
148 ret = snd_soc_jack_new(codec, "Headset Jack",
149 SND_JACK_HEADSET, &hs_jack);
150 if (ret)
151 return ret;
152
153 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
154 hs_jack_pins);
155
156 if (machine_is_omap_4430sdp())
157 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
158 else
159 snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
160
161 return ret;
162}
163
164/* Digital audio interface glue - connects codec <--> CPU */
165static struct snd_soc_dai_link sdp4430_dai = {
166 .name = "TWL6040",
167 .stream_name = "TWL6040",
168 .cpu_dai_name ="omap-mcpdm-dai",
169 .codec_dai_name = "twl6040-hifi",
170 .platform_name = "omap-pcm-audio",
171 .codec_name = "twl6040-codec",
172 .init = sdp4430_twl6040_init,
173 .ops = &sdp4430_ops,
174};
175
176/* Audio machine driver */
177static struct snd_soc_card snd_soc_sdp4430 = {
178 .name = "SDP4430",
179 .dai_link = &sdp4430_dai,
180 .num_links = 1,
181};
182
183static struct platform_device *sdp4430_snd_device;
184
185static int __init sdp4430_soc_init(void)
186{
187 int ret;
188
189 if (!machine_is_omap_4430sdp())
190 return -ENODEV;
191 printk(KERN_INFO "SDP4430 SoC init\n");
192
193 sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
194 if (!sdp4430_snd_device) {
195 printk(KERN_ERR "Platform device allocation failed\n");
196 return -ENOMEM;
197 }
198
199 platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
200
201 ret = platform_device_add(sdp4430_snd_device);
202 if (ret)
203 goto err;
204
205 return 0;
206
207err:
208 printk(KERN_ERR "Unable to add platform device\n");
209 platform_device_put(sdp4430_snd_device);
210 return ret;
211}
212module_init(sdp4430_soc_init);
213
214static void __exit sdp4430_soc_exit(void)
215{
216 platform_device_unregister(sdp4430_snd_device);
217}
218module_exit(sdp4430_soc_exit);
219
220MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
221MODULE_DESCRIPTION("ALSA SoC SDP4430");
222MODULE_LICENSE("GPL");
223