aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap')
-rw-r--r--sound/soc/omap/Kconfig51
-rw-r--r--sound/soc/omap/Makefile10
-rw-r--r--sound/soc/omap/am3517evm.c21
-rw-r--r--sound/soc/omap/igep0020.c120
-rw-r--r--sound/soc/omap/mcbsp.c54
-rw-r--r--sound/soc/omap/mcbsp.h3
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c145
-rw-r--r--sound/soc/omap/omap-dmic.c9
-rw-r--r--sound/soc/omap/omap-hdmi.c17
-rw-r--r--sound/soc/omap/omap-mcbsp.c230
-rw-r--r--sound/soc/omap/omap-mcbsp.h20
-rw-r--r--sound/soc/omap/omap-mcpdm.c92
-rw-r--r--sound/soc/omap/omap-pcm.c236
-rw-r--r--sound/soc/omap/omap-pcm.h4
-rw-r--r--sound/soc/omap/omap-twl4030.c188
-rw-r--r--sound/soc/omap/omap3beagle.c150
-rw-r--r--sound/soc/omap/omap3evm.c118
-rw-r--r--sound/soc/omap/overo.c122
-rw-r--r--sound/soc/omap/zoom2.c4
19 files changed, 579 insertions, 1015 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 57a2fa751085..7048137f9a33 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,7 @@
1config SND_OMAP_SOC 1config SND_OMAP_SOC
2 tristate "SoC Audio for the Texas Instruments OMAP chips" 2 tristate "SoC Audio for the Texas Instruments OMAP chips"
3 depends on ARCH_OMAP 3 depends on ARCH_OMAP && DMA_OMAP
4 select SND_SOC_DMAENGINE_PCM
4 5
5config SND_OMAP_SOC_DMIC 6config SND_OMAP_SOC_DMIC
6 tristate 7 tristate
@@ -60,23 +61,6 @@ config SND_OMAP_SOC_OSK5912
60 help 61 help
61 Say Y if you want to add support for SoC audio on osk5912. 62 Say Y if you want to add support for SoC audio on osk5912.
62 63
63config SND_OMAP_SOC_OVERO
64 tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35"
65 depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35)
66 select SND_OMAP_SOC_MCBSP
67 select SND_SOC_TWL4030
68 help
69 Say Y if you want to add support for SoC audio on the
70 Gumstix Overo or CompuLab CM-T35
71
72config SND_OMAP_SOC_OMAP3EVM
73 tristate "SoC Audio support for OMAP3EVM board"
74 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM
75 select SND_OMAP_SOC_MCBSP
76 select SND_SOC_TWL4030
77 help
78 Say Y if you want to add support for SoC audio on the omap3evm board.
79
80config SND_OMAP_SOC_AM3517EVM 64config SND_OMAP_SOC_AM3517EVM
81 tristate "SoC Audio support for OMAP3517 / AM3517 EVM" 65 tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
82 depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C 66 depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
@@ -95,6 +79,19 @@ config SND_OMAP_SOC_SDP3430
95 Say Y if you want to add support for SoC audio on Texas Instruments 79 Say Y if you want to add support for SoC audio on Texas Instruments
96 SDP3430. 80 SDP3430.
97 81
82config SND_OMAP_SOC_OMAP_TWL4030
83 tristate "SoC Audio support for TI SoC based boards with twl4030 codec"
84 depends on TWL4030_CORE && SND_OMAP_SOC
85 select SND_OMAP_SOC_MCBSP
86 select SND_SOC_TWL4030
87 help
88 Say Y if you want to add support for SoC audio on TI SoC based boards
89 using twl4030 as c codec. This driver currently supports:
90 - Beagleboard or Devkit8000
91 - Gumstix Overo or CompuLab CM-T35/CM-T3730
92 - IGEP v2
93 - OMAP3EVM
94
98config SND_OMAP_SOC_OMAP_ABE_TWL6040 95config SND_OMAP_SOC_OMAP_ABE_TWL6040
99 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" 96 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
100 depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 97 depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4
@@ -127,16 +124,6 @@ config SND_OMAP_SOC_OMAP3_PANDORA
127 help 124 help
128 Say Y if you want to add support for SoC audio on the OMAP3 Pandora. 125 Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
129 126
130config SND_OMAP_SOC_OMAP3_BEAGLE
131 tristate "SoC Audio support for OMAP3 Beagle and Devkit8000"
132 depends on TWL4030_CORE && SND_OMAP_SOC
133 depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000)
134 select SND_OMAP_SOC_MCBSP
135 select SND_SOC_TWL4030
136 help
137 Say Y if you want to add support for SoC audio on the Beagleboard or
138 the clone Devkit8000.
139
140config SND_OMAP_SOC_ZOOM2 127config SND_OMAP_SOC_ZOOM2
141 tristate "SoC Audio support for Zoom2" 128 tristate "SoC Audio support for Zoom2"
142 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 129 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
@@ -144,11 +131,3 @@ config SND_OMAP_SOC_ZOOM2
144 select SND_SOC_TWL4030 131 select SND_SOC_TWL4030
145 help 132 help
146 Say Y if you want to add support for Soc audio on Zoom2 board. 133 Say Y if you want to add support for Soc audio on Zoom2 board.
147
148config SND_OMAP_SOC_IGEP0020
149 tristate "SoC Audio support for IGEP v2"
150 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020
151 select SND_OMAP_SOC_MCBSP
152 select SND_SOC_TWL4030
153 help
154 Say Y if you want to add support for Soc audio on IGEP v2 board.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 0e14dd322565..19637e55ea48 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -16,29 +16,23 @@ snd-soc-n810-objs := n810.o
16snd-soc-rx51-objs := rx51.o 16snd-soc-rx51-objs := rx51.o
17snd-soc-ams-delta-objs := ams-delta.o 17snd-soc-ams-delta-objs := ams-delta.o
18snd-soc-osk5912-objs := osk5912.o 18snd-soc-osk5912-objs := osk5912.o
19snd-soc-overo-objs := overo.o
20snd-soc-omap3evm-objs := omap3evm.o
21snd-soc-am3517evm-objs := am3517evm.o 19snd-soc-am3517evm-objs := am3517evm.o
22snd-soc-sdp3430-objs := sdp3430.o 20snd-soc-sdp3430-objs := sdp3430.o
23snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o 21snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
22snd-soc-omap-twl4030-objs := omap-twl4030.o
24snd-soc-omap3pandora-objs := omap3pandora.o 23snd-soc-omap3pandora-objs := omap3pandora.o
25snd-soc-omap3beagle-objs := omap3beagle.o
26snd-soc-zoom2-objs := zoom2.o 24snd-soc-zoom2-objs := zoom2.o
27snd-soc-igep0020-objs := igep0020.o
28snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o 25snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o
29 26
30obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 27obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
31obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o 28obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
32obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o 29obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
33obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 30obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
34obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
35obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o 31obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
36obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
37obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o 32obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
38obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 33obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
39obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o 34obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
35obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o
40obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 36obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
41obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
42obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o 37obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
43obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
44obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o 38obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 009533ab8d18..77a87012977c 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -41,32 +41,15 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
41{ 41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *codec_dai = rtd->codec_dai; 43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
44 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
45 int ret; 44 int ret;
46 45
47 /* Set the codec system clock for DAC and ADC */ 46 /* Set the codec system clock for DAC and ADC */
48 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 47 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
49 CODEC_CLOCK, SND_SOC_CLOCK_IN); 48 CODEC_CLOCK, SND_SOC_CLOCK_IN);
50 if (ret < 0) { 49 if (ret < 0)
51 printk(KERN_ERR "can't set codec system clock\n"); 50 printk(KERN_ERR "can't set codec system clock\n");
52 return ret;
53 }
54
55 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0,
56 SND_SOC_CLOCK_IN);
57 if (ret < 0) {
58 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n");
59 return ret;
60 }
61 51
62 snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, 52 return ret;
63 SND_SOC_CLOCK_IN);
64 if (ret < 0) {
65 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
66 return ret;
67 }
68
69 return 0;
70} 53}
71 54
72static struct snd_soc_ops am3517evm_ops = { 55static struct snd_soc_ops am3517evm_ops = {
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
deleted file mode 100644
index e8357819175b..000000000000
--- a/sound/soc/omap/igep0020.c
+++ /dev/null
@@ -1,120 +0,0 @@
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 <linux/module.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/soc.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <plat/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36
37static int igep2_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 int ret;
43
44 /* Set the codec system clock for DAC and ADC */
45 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
46 SND_SOC_CLOCK_IN);
47 if (ret < 0) {
48 printk(KERN_ERR "can't set codec system clock\n");
49 return ret;
50 }
51
52 return 0;
53}
54
55static struct snd_soc_ops igep2_ops = {
56 .hw_params = igep2_hw_params,
57};
58
59/* Digital audio interface glue - connects codec <--> CPU */
60static struct snd_soc_dai_link igep2_dai = {
61 .name = "TWL4030",
62 .stream_name = "TWL4030",
63 .cpu_dai_name = "omap-mcbsp.2",
64 .codec_dai_name = "twl4030-hifi",
65 .platform_name = "omap-pcm-audio",
66 .codec_name = "twl4030-codec",
67 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
68 SND_SOC_DAIFMT_CBM_CFM,
69 .ops = &igep2_ops,
70};
71
72/* Audio machine driver */
73static struct snd_soc_card snd_soc_card_igep2 = {
74 .name = "igep2",
75 .owner = THIS_MODULE,
76 .dai_link = &igep2_dai,
77 .num_links = 1,
78};
79
80static struct platform_device *igep2_snd_device;
81
82static int __init igep2_soc_init(void)
83{
84 int ret;
85
86 if (!machine_is_igep0020())
87 return -ENODEV;
88 printk(KERN_INFO "IGEP v2 SoC init\n");
89
90 igep2_snd_device = platform_device_alloc("soc-audio", -1);
91 if (!igep2_snd_device) {
92 printk(KERN_ERR "Platform device allocation failed\n");
93 return -ENOMEM;
94 }
95
96 platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);
97
98 ret = platform_device_add(igep2_snd_device);
99 if (ret)
100 goto err1;
101
102 return 0;
103
104err1:
105 printk(KERN_ERR "Unable to add platform device\n");
106 platform_device_put(igep2_snd_device);
107
108 return ret;
109}
110module_init(igep2_soc_init);
111
112static void __exit igep2_soc_exit(void)
113{
114 platform_device_unregister(igep2_snd_device);
115}
116module_exit(igep2_soc_exit);
117
118MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>");
119MODULE_DESCRIPTION("ALSA SoC IGEP v2");
120MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index d33c48baaf71..bc06175e6367 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -24,6 +24,7 @@
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/pm_runtime.h>
27 28
28#include <plat/mcbsp.h> 29#include <plat/mcbsp.h>
29 30
@@ -726,50 +727,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
726 727
727int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) 728int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
728{ 729{
730 struct clk *fck_src;
729 const char *src; 731 const char *src;
732 int r;
730 733
731 if (fck_src_id == MCBSP_CLKS_PAD_SRC) 734 if (fck_src_id == MCBSP_CLKS_PAD_SRC)
732 src = "clks_ext"; 735 src = "pad_fck";
733 else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) 736 else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
734 src = "clks_fclk"; 737 src = "prcm_fck";
735 else 738 else
736 return -EINVAL; 739 return -EINVAL;
737 740
738 if (mcbsp->pdata->set_clk_src) 741 fck_src = clk_get(mcbsp->dev, src);
739 return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); 742 if (IS_ERR(fck_src)) {
740 else 743 dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src);
741 return -EINVAL; 744 return -EINVAL;
742} 745 }
743
744int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
745{
746 const char *signal, *src;
747 746
748 if (!mcbsp->pdata->mux_signal) 747 pm_runtime_put_sync(mcbsp->dev);
749 return -EINVAL;
750 748
751 switch (mux) { 749 r = clk_set_parent(mcbsp->fclk, fck_src);
752 case CLKR_SRC_CLKR: 750 if (r) {
753 signal = "clkr"; 751 dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n",
754 src = "clkr"; 752 src);
755 break; 753 clk_put(fck_src);
756 case CLKR_SRC_CLKX: 754 return r;
757 signal = "clkr";
758 src = "clkx";
759 break;
760 case FSR_SRC_FSR:
761 signal = "fsr";
762 src = "fsr";
763 break;
764 case FSR_SRC_FSX:
765 signal = "fsr";
766 src = "fsx";
767 break;
768 default:
769 return -EINVAL;
770 } 755 }
771 756
772 return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); 757 pm_runtime_get_sync(mcbsp->dev);
758
759 clk_put(fck_src);
760
761 return 0;
762
773} 763}
774 764
775#define max_thres(m) (mcbsp->pdata->buffer_size) 765#define max_thres(m) (mcbsp->pdata->buffer_size)
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index 262a6152111f..49a67259ce5a 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx);
334/* McBSP functional clock source changing function */ 334/* McBSP functional clock source changing function */
335int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); 335int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
336 336
337/* McBSP signal muxing API */
338int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux);
339
340/* Sidetone specific API */ 337/* Sidetone specific API */
341int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); 338int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain);
342int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); 339int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain);
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 9d93793d3077..be525dfe9faa 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -25,6 +25,7 @@
25#include <linux/mfd/twl6040.h> 25#include <linux/mfd/twl6040.h>
26#include <linux/platform_data/omap-abe-twl6040.h> 26#include <linux/platform_data/omap-abe-twl6040.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/of.h>
28 29
29#include <sound/core.h> 30#include <sound/core.h>
30#include <sound/pcm.h> 31#include <sound/pcm.h>
@@ -43,6 +44,8 @@
43struct abe_twl6040 { 44struct abe_twl6040 {
44 int jack_detection; /* board can detect jack events */ 45 int jack_detection; /* board can detect jack events */
45 int mclk_freq; /* MCLK frequency speed for twl6040 */ 46 int mclk_freq; /* MCLK frequency speed for twl6040 */
47
48 struct platform_device *dmic_codec_dev;
46}; 49};
47 50
48static int omap_abe_hw_params(struct snd_pcm_substream *substream, 51static int omap_abe_hw_params(struct snd_pcm_substream *substream,
@@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
185 int hs_trim; 188 int hs_trim;
186 int ret = 0; 189 int ret = 0;
187 190
188 /* Disable not connected paths if not used */
189 twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
190 twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
191 twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
192 twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
193 twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
194 twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
195 twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
196 twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
197 twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
198
199 /* 191 /*
200 * Configure McPDM offset cancellation based on the HSOTRIM value from 192 * Configure McPDM offset cancellation based on the HSOTRIM value from
201 * twl6040. 193 * twl6040.
@@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
216 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); 208 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
217 } 209 }
218 210
211 /*
212 * NULL pdata means we booted with DT. In this case the routing is
213 * provided and the card is fully routed, no need to mark pins.
214 */
215 if (!pdata)
216 return ret;
217
218 /* Disable not connected paths if not used */
219 twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
220 twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
221 twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
222 twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
223 twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
224 twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
225 twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
226 twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
227 twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
228
219 return ret; 229 return ret;
220} 230}
221 231
@@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = {
270static __devinit int omap_abe_probe(struct platform_device *pdev) 280static __devinit int omap_abe_probe(struct platform_device *pdev)
271{ 281{
272 struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); 282 struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
283 struct device_node *node = pdev->dev.of_node;
273 struct snd_soc_card *card = &omap_abe_card; 284 struct snd_soc_card *card = &omap_abe_card;
274 struct abe_twl6040 *priv; 285 struct abe_twl6040 *priv;
275 int num_links = 0; 286 int num_links = 0;
276 int ret; 287 int ret = 0;
277 288
278 card->dev = &pdev->dev; 289 card->dev = &pdev->dev;
279 290
280 if (!pdata) {
281 dev_err(&pdev->dev, "Missing pdata\n");
282 return -ENODEV;
283 }
284
285 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); 291 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
286 if (priv == NULL) 292 if (priv == NULL)
287 return -ENOMEM; 293 return -ENOMEM;
288 294
289 if (pdata->card_name) { 295 priv->dmic_codec_dev = ERR_PTR(-EINVAL);
290 card->name = pdata->card_name; 296
297 if (node) {
298 struct device_node *dai_node;
299
300 if (snd_soc_of_parse_card_name(card, "ti,model")) {
301 dev_err(&pdev->dev, "Card name is not provided\n");
302 return -ENODEV;
303 }
304
305 ret = snd_soc_of_parse_audio_routing(card,
306 "ti,audio-routing");
307 if (ret) {
308 dev_err(&pdev->dev,
309 "Error while parsing DAPM routing\n");
310 return ret;
311 }
312
313 dai_node = of_parse_phandle(node, "ti,mcpdm", 0);
314 if (!dai_node) {
315 dev_err(&pdev->dev, "McPDM node is not provided\n");
316 return -EINVAL;
317 }
318 abe_twl6040_dai_links[0].cpu_dai_name = NULL;
319 abe_twl6040_dai_links[0].cpu_of_node = dai_node;
320
321 dai_node = of_parse_phandle(node, "ti,dmic", 0);
322 if (dai_node) {
323 num_links = 2;
324 abe_twl6040_dai_links[1].cpu_dai_name = NULL;
325 abe_twl6040_dai_links[1].cpu_of_node = dai_node;
326
327 priv->dmic_codec_dev = platform_device_register_simple(
328 "dmic-codec", -1, NULL, 0);
329 if (IS_ERR(priv->dmic_codec_dev)) {
330 dev_err(&pdev->dev,
331 "Can't instantiate dmic-codec\n");
332 return PTR_ERR(priv->dmic_codec_dev);
333 }
334 } else {
335 num_links = 1;
336 }
337
338 of_property_read_u32(node, "ti,jack-detection",
339 &priv->jack_detection);
340 of_property_read_u32(node, "ti,mclk-freq",
341 &priv->mclk_freq);
342 if (!priv->mclk_freq) {
343 dev_err(&pdev->dev, "MCLK frequency not provided\n");
344 ret = -EINVAL;
345 goto err_unregister;
346 }
347
348 omap_abe_card.fully_routed = 1;
349 } else if (pdata) {
350 if (pdata->card_name) {
351 card->name = pdata->card_name;
352 } else {
353 dev_err(&pdev->dev, "Card name is not provided\n");
354 return -ENODEV;
355 }
356
357 if (pdata->has_dmic)
358 num_links = 2;
359 else
360 num_links = 1;
361
362 priv->jack_detection = pdata->jack_detection;
363 priv->mclk_freq = pdata->mclk_freq;
291 } else { 364 } else {
292 dev_err(&pdev->dev, "Card name is not provided\n"); 365 dev_err(&pdev->dev, "Missing pdata\n");
293 return -ENODEV; 366 return -ENODEV;
294 } 367 }
295 368
296 priv->jack_detection = pdata->jack_detection;
297 priv->mclk_freq = pdata->mclk_freq;
298
299 369
300 if (!priv->mclk_freq) { 370 if (!priv->mclk_freq) {
301 dev_err(&pdev->dev, "MCLK frequency missing\n"); 371 dev_err(&pdev->dev, "MCLK frequency missing\n");
302 return -ENODEV; 372 ret = -ENODEV;
373 goto err_unregister;
303 } 374 }
304 375
305 if (pdata->has_dmic)
306 num_links = 2;
307 else
308 num_links = 1;
309
310 card->dai_link = abe_twl6040_dai_links; 376 card->dai_link = abe_twl6040_dai_links;
311 card->num_links = num_links; 377 card->num_links = num_links;
312 378
313 snd_soc_card_set_drvdata(card, priv); 379 snd_soc_card_set_drvdata(card, priv);
314 380
315 ret = snd_soc_register_card(card); 381 ret = snd_soc_register_card(card);
316 if (ret) 382 if (ret) {
317 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 383 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
318 ret); 384 ret);
385 goto err_unregister;
386 }
387
388 return 0;
389
390err_unregister:
391 if (!IS_ERR(priv->dmic_codec_dev))
392 platform_device_unregister(priv->dmic_codec_dev);
319 393
320 return ret; 394 return ret;
321} 395}
@@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
323static int __devexit omap_abe_remove(struct platform_device *pdev) 397static int __devexit omap_abe_remove(struct platform_device *pdev)
324{ 398{
325 struct snd_soc_card *card = platform_get_drvdata(pdev); 399 struct snd_soc_card *card = platform_get_drvdata(pdev);
400 struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
326 401
327 snd_soc_unregister_card(card); 402 snd_soc_unregister_card(card);
328 403
404 if (!IS_ERR(priv->dmic_codec_dev))
405 platform_device_unregister(priv->dmic_codec_dev);
406
329 return 0; 407 return 0;
330} 408}
331 409
410static const struct of_device_id omap_abe_of_match[] = {
411 {.compatible = "ti,abe-twl6040", },
412 { },
413};
414MODULE_DEVICE_TABLE(of, omap_abe_of_match);
415
332static struct platform_driver omap_abe_driver = { 416static struct platform_driver omap_abe_driver = {
333 .driver = { 417 .driver = {
334 .name = "omap-abe-twl6040", 418 .name = "omap-abe-twl6040",
335 .owner = THIS_MODULE, 419 .owner = THIS_MODULE,
336 .pm = &snd_soc_pm_ops, 420 .pm = &snd_soc_pm_ops,
421 .of_match_table = omap_abe_of_match,
337 }, 422 },
338 .probe = omap_abe_probe, 423 .probe = omap_abe_probe,
339 .remove = __devexit_p(omap_abe_remove), 424 .remove = __devexit_p(omap_abe_remove),
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 75f5dca0e8d2..68f2cd1a9206 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -33,7 +33,6 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
35#include <linux/of_device.h> 35#include <linux/of_device.h>
36#include <plat/dma.h>
37 36
38#include <sound/core.h> 37#include <sound/core.h>
39#include <sound/pcm.h> 38#include <sound/pcm.h>
@@ -63,8 +62,6 @@ struct omap_dmic {
63 */ 62 */
64static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { 63static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
65 .name = "DMIC capture", 64 .name = "DMIC capture",
66 .data_type = OMAP_DMA_DATA_TYPE_S32,
67 .sync_mode = OMAP_DMA_SYNC_PACKET,
68}; 65};
69 66
70static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) 67static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
@@ -121,6 +118,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
121 118
122 mutex_unlock(&dmic->mutex); 119 mutex_unlock(&dmic->mutex);
123 120
121 snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
124 return ret; 122 return ret;
125} 123}
126 124
@@ -205,6 +203,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
205 struct snd_soc_dai *dai) 203 struct snd_soc_dai *dai)
206{ 204{
207 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); 205 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
206 struct omap_pcm_dma_data *dma_data;
208 int channels; 207 int channels;
209 208
210 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); 209 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
@@ -230,8 +229,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
230 } 229 }
231 230
232 /* packet size is threshold * channels */ 231 /* packet size is threshold * channels */
233 omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels; 232 dma_data = snd_soc_dai_get_dma_data(dai, substream);
234 snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); 233 dma_data->packet_size = dmic->threshold * channels;
235 234
236 return 0; 235 return 0;
237} 236}
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index a08245d9203c..f59c69fb400e 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -34,7 +34,6 @@
34#include <sound/asoundef.h> 34#include <sound/asoundef.h>
35#include <video/omapdss.h> 35#include <video/omapdss.h>
36 36
37#include <plat/dma.h>
38#include "omap-pcm.h" 37#include "omap-pcm.h"
39#include "omap-hdmi.h" 38#include "omap-hdmi.h"
40 39
@@ -68,6 +67,9 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
68 dev_err(dai->dev, "audio not supported\n"); 67 dev_err(dai->dev, "audio not supported\n");
69 return -ENODEV; 68 return -ENODEV;
70 } 69 }
70
71 snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params);
72
71 return 0; 73 return 0;
72} 74}
73 75
@@ -86,24 +88,24 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
86 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); 88 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
87 struct snd_aes_iec958 *iec = &priv->iec; 89 struct snd_aes_iec958 *iec = &priv->iec;
88 struct snd_cea_861_aud_if *cea = &priv->cea; 90 struct snd_cea_861_aud_if *cea = &priv->cea;
91 struct omap_pcm_dma_data *dma_data;
89 int err = 0; 92 int err = 0;
90 93
94 dma_data = snd_soc_dai_get_dma_data(dai, substream);
95
91 switch (params_format(params)) { 96 switch (params_format(params)) {
92 case SNDRV_PCM_FORMAT_S16_LE: 97 case SNDRV_PCM_FORMAT_S16_LE:
93 priv->dma_params.packet_size = 16; 98 dma_data->packet_size = 16;
94 break; 99 break;
95 case SNDRV_PCM_FORMAT_S24_LE: 100 case SNDRV_PCM_FORMAT_S24_LE:
96 priv->dma_params.packet_size = 32; 101 dma_data->packet_size = 32;
97 break; 102 break;
98 default: 103 default:
99 dev_err(dai->dev, "format not supported!\n"); 104 dev_err(dai->dev, "format not supported!\n");
100 return -EINVAL; 105 return -EINVAL;
101 } 106 }
102 107
103 priv->dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; 108 dma_data->data_type = 32;
104
105 snd_soc_dai_set_dma_data(dai, substream,
106 &priv->dma_params);
107 109
108 /* 110 /*
109 * fill the IEC-60958 channel status word 111 * fill the IEC-60958 channel status word
@@ -290,7 +292,6 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
290 292
291 hdmi_data->dma_params.dma_req = hdmi_rsrc->start; 293 hdmi_data->dma_params.dma_req = hdmi_rsrc->start;
292 hdmi_data->dma_params.name = "HDMI playback"; 294 hdmi_data->dma_params.name = "HDMI playback";
293 hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET;
294 295
295 /* 296 /*
296 * TODO: We assume that there is only one DSS HDMI device. Future 297 * TODO: We assume that there is only one DSS HDMI device. Future
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index acdd3ef14e08..fef2f5933bb2 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -26,13 +26,14 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/device.h> 27#include <linux/device.h>
28#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
29#include <linux/of.h>
30#include <linux/of_device.h>
29#include <sound/core.h> 31#include <sound/core.h>
30#include <sound/pcm.h> 32#include <sound/pcm.h>
31#include <sound/pcm_params.h> 33#include <sound/pcm_params.h>
32#include <sound/initval.h> 34#include <sound/initval.h>
33#include <sound/soc.h> 35#include <sound/soc.h>
34 36
35#include <plat/dma.h>
36#include <plat/mcbsp.h> 37#include <plat/mcbsp.h>
37#include "mcbsp.h" 38#include "mcbsp.h"
38#include "omap-mcbsp.h" 39#include "omap-mcbsp.h"
@@ -79,9 +80,6 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
79 */ 80 */
80 if (dma_data->packet_size) 81 if (dma_data->packet_size)
81 words = dma_data->packet_size; 82 words = dma_data->packet_size;
82 else if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
83 words = snd_pcm_lib_period_bytes(substream) /
84 (mcbsp->wlen / 8);
85 else 83 else
86 words = 1; 84 words = 1;
87 85
@@ -153,6 +151,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
153 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); 151 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
154 } 152 }
155 153
154 snd_soc_dai_set_dma_data(cpu_dai, substream,
155 &mcbsp->dma_data[substream->stream]);
156
156 return err; 157 return err;
157} 158}
158 159
@@ -226,20 +227,18 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
226 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); 227 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
227 struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; 228 struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
228 struct omap_pcm_dma_data *dma_data; 229 struct omap_pcm_dma_data *dma_data;
229 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; 230 int wlen, channels, wpf;
230 int pkt_size = 0; 231 int pkt_size = 0;
231 unsigned int format, div, framesize, master; 232 unsigned int format, div, framesize, master;
232 233
233 dma_data = &mcbsp->dma_data[substream->stream]; 234 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
234 channels = params_channels(params); 235 channels = params_channels(params);
235 236
236 switch (params_format(params)) { 237 switch (params_format(params)) {
237 case SNDRV_PCM_FORMAT_S16_LE: 238 case SNDRV_PCM_FORMAT_S16_LE:
238 dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
239 wlen = 16; 239 wlen = 16;
240 break; 240 break;
241 case SNDRV_PCM_FORMAT_S32_LE: 241 case SNDRV_PCM_FORMAT_S32_LE:
242 dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
243 wlen = 32; 242 wlen = 32;
244 break; 243 break;
245 default: 244 default:
@@ -249,6 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
249 dma_data->set_threshold = omap_mcbsp_set_threshold; 248 dma_data->set_threshold = omap_mcbsp_set_threshold;
250 if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { 249 if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
251 int period_words, max_thrsh; 250 int period_words, max_thrsh;
251 int divider = 0;
252 252
253 period_words = params_period_bytes(params) / (wlen / 8); 253 period_words = params_period_bytes(params) / (wlen / 8);
254 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 254 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -256,46 +256,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
256 else 256 else
257 max_thrsh = mcbsp->max_rx_thres; 257 max_thrsh = mcbsp->max_rx_thres;
258 /* 258 /*
259 * If the period contains less or equal number of words, 259 * Use sDMA packet mode if McBSP is in threshold mode:
260 * we are using the original threshold mode setup: 260 * If period words less than the FIFO size the packet
261 * McBSP threshold = sDMA frame size = period_size 261 * size is set to the number of period words, otherwise
262 * Otherwise we switch to sDMA packet mode: 262 * Look for the biggest threshold value which divides
263 * McBSP threshold = sDMA packet size 263 * the period size evenly.
264 * sDMA frame size = period size
265 */ 264 */
266 if (period_words > max_thrsh) { 265 divider = period_words / max_thrsh;
267 int divider = 0; 266 if (period_words % max_thrsh)
268 267 divider++;
269 /* 268 while (period_words % divider &&
270 * Look for the biggest threshold value, which 269 divider < period_words)
271 * divides the period size evenly. 270 divider++;
272 */ 271 if (divider == period_words)
273 divider = period_words / max_thrsh; 272 return -EINVAL;
274 if (period_words % max_thrsh) 273
275 divider++; 274 pkt_size = period_words / divider;
276 while (period_words % divider &&
277 divider < period_words)
278 divider++;
279 if (divider == period_words)
280 return -EINVAL;
281
282 pkt_size = period_words / divider;
283 sync_mode = OMAP_DMA_SYNC_PACKET;
284 } else {
285 sync_mode = OMAP_DMA_SYNC_FRAME;
286 }
287 } else if (channels > 1) { 275 } else if (channels > 1) {
288 /* Use packet mode for non mono streams */ 276 /* Use packet mode for non mono streams */
289 pkt_size = channels; 277 pkt_size = channels;
290 sync_mode = OMAP_DMA_SYNC_PACKET;
291 } 278 }
292 } 279 }
293 280
294 dma_data->sync_mode = sync_mode;
295 dma_data->packet_size = pkt_size; 281 dma_data->packet_size = pkt_size;
296 282
297 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
298
299 if (mcbsp->configured) { 283 if (mcbsp->configured) {
300 /* McBSP already configured by another stream */ 284 /* McBSP already configured by another stream */
301 return 0; 285 return 0;
@@ -398,12 +382,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
398 /* Generic McBSP register settings */ 382 /* Generic McBSP register settings */
399 regs->spcr2 |= XINTM(3) | FREE; 383 regs->spcr2 |= XINTM(3) | FREE;
400 regs->spcr1 |= RINTM(3); 384 regs->spcr1 |= RINTM(3);
401 /* RFIG and XFIG are not defined in 34xx */ 385 /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */
402 if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { 386 if (!mcbsp->pdata->has_ccr) {
403 regs->rcr2 |= RFIG; 387 regs->rcr2 |= RFIG;
404 regs->xcr2 |= XFIG; 388 regs->xcr2 |= XFIG;
405 } 389 }
406 if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { 390
391 /* Configure XCCR/RCCR only for revisions which have ccr registers */
392 if (mcbsp->pdata->has_ccr) {
407 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; 393 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
408 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; 394 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
409 } 395 }
@@ -516,21 +502,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
516 return -EBUSY; 502 return -EBUSY;
517 } 503 }
518 504
519 if (clk_id == OMAP_MCBSP_SYSCLK_CLK || 505 mcbsp->in_freq = freq;
520 clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || 506 regs->srgr2 &= ~CLKSM;
521 clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || 507 regs->pcr0 &= ~SCLKME;
522 clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT ||
523 clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) {
524 mcbsp->in_freq = freq;
525 regs->srgr2 &= ~CLKSM;
526 regs->pcr0 &= ~SCLKME;
527 } else if (cpu_class_is_omap1()) {
528 /*
529 * McBSP CLKR/FSR signal muxing functions are only available on
530 * OMAP2 or newer versions
531 */
532 return -EINVAL;
533 }
534 508
535 switch (clk_id) { 509 switch (clk_id) {
536 case OMAP_MCBSP_SYSCLK_CLK: 510 case OMAP_MCBSP_SYSCLK_CLK:
@@ -558,20 +532,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
558 case OMAP_MCBSP_SYSCLK_CLKR_EXT: 532 case OMAP_MCBSP_SYSCLK_CLKR_EXT:
559 regs->pcr0 |= SCLKME; 533 regs->pcr0 |= SCLKME;
560 break; 534 break;
561
562
563 case OMAP_MCBSP_CLKR_SRC_CLKR:
564 err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR);
565 break;
566 case OMAP_MCBSP_CLKR_SRC_CLKX:
567 err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX);
568 break;
569 case OMAP_MCBSP_FSR_SRC_FSR:
570 err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR);
571 break;
572 case OMAP_MCBSP_FSR_SRC_FSX:
573 err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX);
574 break;
575 default: 535 default:
576 err = -ENODEV; 536 err = -ENODEV;
577 } 537 }
@@ -641,9 +601,9 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
641 return 0; 601 return 0;
642} 602}
643 603
644#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ 604#define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \
645static int \ 605static int \
646omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ 606omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
647 struct snd_ctl_elem_value *uc) \ 607 struct snd_ctl_elem_value *uc) \
648{ \ 608{ \
649 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ 609 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
@@ -659,11 +619,10 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
659 \ 619 \
660 /* OMAP McBSP implementation uses index values 0..4 */ \ 620 /* OMAP McBSP implementation uses index values 0..4 */ \
661 return omap_st_set_chgain(mcbsp, channel, val); \ 621 return omap_st_set_chgain(mcbsp, channel, val); \
662} 622} \
663 623 \
664#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \
665static int \ 624static int \
666omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ 625omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
667 struct snd_ctl_elem_value *uc) \ 626 struct snd_ctl_elem_value *uc) \
668{ \ 627{ \
669 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ 628 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
@@ -677,10 +636,8 @@ omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
677 return 0; \ 636 return 0; \
678} 637}
679 638
680OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) 639OMAP_MCBSP_ST_CHANNEL_VOLUME(0)
681OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) 640OMAP_MCBSP_ST_CHANNEL_VOLUME(1)
682OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0)
683OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1)
684 641
685static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, 642static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
686 struct snd_ctl_elem_value *ucontrol) 643 struct snd_ctl_elem_value *ucontrol)
@@ -710,41 +667,34 @@ static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
710 return 0; 667 return 0;
711} 668}
712 669
713static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { 670#define OMAP_MCBSP_ST_CONTROLS(port) \
714 SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, 671static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \
715 omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), 672SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \
716 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", 673 omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \
717 -32768, 32767, 674OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \
718 omap_mcbsp_get_st_ch0_volume, 675 -32768, 32767, \
719 omap_mcbsp_set_st_ch0_volume), 676 omap_mcbsp_get_st_ch0_volume, \
720 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", 677 omap_mcbsp_set_st_ch0_volume), \
721 -32768, 32767, 678OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \
722 omap_mcbsp_get_st_ch1_volume, 679 -32768, 32767, \
723 omap_mcbsp_set_st_ch1_volume), 680 omap_mcbsp_get_st_ch1_volume, \
724}; 681 omap_mcbsp_set_st_ch1_volume), \
682}
725 683
726static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { 684OMAP_MCBSP_ST_CONTROLS(2);
727 SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, 685OMAP_MCBSP_ST_CONTROLS(3);
728 omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
729 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
730 -32768, 32767,
731 omap_mcbsp_get_st_ch0_volume,
732 omap_mcbsp_set_st_ch0_volume),
733 OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
734 -32768, 32767,
735 omap_mcbsp_get_st_ch1_volume,
736 omap_mcbsp_set_st_ch1_volume),
737};
738 686
739int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) 687int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
740{ 688{
741 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 689 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
742 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); 690 struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
743 691
744 if (!mcbsp->st_data) 692 if (!mcbsp->st_data) {
745 return -ENODEV; 693 dev_warn(mcbsp->dev, "No sidetone data for port\n");
694 return 0;
695 }
746 696
747 switch (cpu_dai->id) { 697 switch (mcbsp->id) {
748 case 2: /* McBSP 2 */ 698 case 2: /* McBSP 2 */
749 return snd_soc_add_dai_controls(cpu_dai, 699 return snd_soc_add_dai_controls(cpu_dai,
750 omap_mcbsp2_st_controls, 700 omap_mcbsp2_st_controls,
@@ -761,13 +711,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
761} 711}
762EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); 712EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
763 713
714static struct omap_mcbsp_platform_data omap2420_pdata = {
715 .reg_step = 4,
716 .reg_size = 2,
717};
718
719static struct omap_mcbsp_platform_data omap2430_pdata = {
720 .reg_step = 4,
721 .reg_size = 4,
722 .has_ccr = true,
723};
724
725static struct omap_mcbsp_platform_data omap3_pdata = {
726 .reg_step = 4,
727 .reg_size = 4,
728 .has_ccr = true,
729 .has_wakeup = true,
730};
731
732static struct omap_mcbsp_platform_data omap4_pdata = {
733 .reg_step = 4,
734 .reg_size = 4,
735 .has_ccr = true,
736 .has_wakeup = true,
737};
738
739static const struct of_device_id omap_mcbsp_of_match[] = {
740 {
741 .compatible = "ti,omap2420-mcbsp",
742 .data = &omap2420_pdata,
743 },
744 {
745 .compatible = "ti,omap2430-mcbsp",
746 .data = &omap2430_pdata,
747 },
748 {
749 .compatible = "ti,omap3-mcbsp",
750 .data = &omap3_pdata,
751 },
752 {
753 .compatible = "ti,omap4-mcbsp",
754 .data = &omap4_pdata,
755 },
756 { },
757};
758MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match);
759
764static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) 760static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
765{ 761{
766 struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); 762 struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
767 struct omap_mcbsp *mcbsp; 763 struct omap_mcbsp *mcbsp;
764 const struct of_device_id *match;
768 int ret; 765 int ret;
769 766
770 if (!pdata) { 767 match = of_match_device(omap_mcbsp_of_match, &pdev->dev);
768 if (match) {
769 struct device_node *node = pdev->dev.of_node;
770 int buffer_size;
771
772 pdata = devm_kzalloc(&pdev->dev,
773 sizeof(struct omap_mcbsp_platform_data),
774 GFP_KERNEL);
775 if (!pdata)
776 return -ENOMEM;
777
778 memcpy(pdata, match->data, sizeof(*pdata));
779 if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size))
780 pdata->buffer_size = buffer_size;
781 } else if (!pdata) {
771 dev_err(&pdev->dev, "missing platform data.\n"); 782 dev_err(&pdev->dev, "missing platform data.\n");
772 return -EINVAL; 783 return -EINVAL;
773 } 784 }
@@ -809,6 +820,7 @@ static struct platform_driver asoc_mcbsp_driver = {
809 .driver = { 820 .driver = {
810 .name = "omap-mcbsp", 821 .name = "omap-mcbsp",
811 .owner = THIS_MODULE, 822 .owner = THIS_MODULE,
823 .of_match_table = omap_mcbsp_of_match,
812 }, 824 },
813 825
814 .probe = asoc_mcbsp_probe, 826 .probe = asoc_mcbsp_probe,
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index f877b16f19c9..ba8386a0d8dc 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk {
32 OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ 32 OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */
33 OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ 33 OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */
34 OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ 34 OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */
35 OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */
36 OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */
37 OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */
38 OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */
39}; 35};
40 36
41/* McBSP dividers */ 37/* McBSP dividers */
@@ -43,22 +39,6 @@ enum omap_mcbsp_div {
43 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ 39 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */
44}; 40};
45 41
46#if defined(CONFIG_SOC_OMAP2420)
47#define NUM_LINKS 2
48#endif
49#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
50#undef NUM_LINKS
51#define NUM_LINKS 3
52#endif
53#if defined(CONFIG_ARCH_OMAP4)
54#undef NUM_LINKS
55#define NUM_LINKS 4
56#endif
57#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430)
58#undef NUM_LINKS
59#define NUM_LINKS 5
60#endif
61
62int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); 42int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
63 43
64#endif 44#endif
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 2c66e2498a45..775565032ce3 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -40,7 +40,6 @@
40#include <sound/pcm_params.h> 40#include <sound/pcm_params.h>
41#include <sound/soc.h> 41#include <sound/soc.h>
42 42
43#include <plat/dma.h>
44#include <plat/omap_hwmod.h> 43#include <plat/omap_hwmod.h>
45#include "omap-mcpdm.h" 44#include "omap-mcpdm.h"
46#include "omap-pcm.h" 45#include "omap-pcm.h"
@@ -71,17 +70,9 @@ struct omap_mcpdm {
71static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { 70static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
72 { 71 {
73 .name = "Audio playback", 72 .name = "Audio playback",
74 .dma_req = OMAP44XX_DMA_MCPDM_DL,
75 .data_type = OMAP_DMA_DATA_TYPE_S32,
76 .sync_mode = OMAP_DMA_SYNC_PACKET,
77 .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
78 }, 73 },
79 { 74 {
80 .name = "Audio capture", 75 .name = "Audio capture",
81 .dma_req = OMAP44XX_DMA_MCPDM_UP,
82 .data_type = OMAP_DMA_DATA_TYPE_S32,
83 .sync_mode = OMAP_DMA_SYNC_PACKET,
84 .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
85 }, 76 },
86}; 77};
87 78
@@ -276,9 +267,11 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
276 } 267 }
277 omap_mcpdm_open_streams(mcpdm); 268 omap_mcpdm_open_streams(mcpdm);
278 } 269 }
279
280 mutex_unlock(&mcpdm->mutex); 270 mutex_unlock(&mcpdm->mutex);
281 271
272 snd_soc_dai_set_dma_data(dai, substream,
273 &omap_mcpdm_dai_dma_params[substream->stream]);
274
282 return 0; 275 return 0;
283} 276}
284 277
@@ -333,7 +326,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
333 return -EINVAL; 326 return -EINVAL;
334 } 327 }
335 328
336 dma_data = &omap_mcpdm_dai_dma_params[stream]; 329 dma_data = snd_soc_dai_get_dma_data(dai, substream);
337 330
338 /* Configure McPDM channels, and DMA packet size */ 331 /* Configure McPDM channels, and DMA packet size */
339 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 332 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -345,8 +338,6 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
345 dma_data->packet_size = mcpdm->up_threshold * channels; 338 dma_data->packet_size = mcpdm->up_threshold * channels;
346 } 339 }
347 340
348 snd_soc_dai_set_dma_data(dai, substream, dma_data);
349
350 return 0; 341 return 0;
351} 342}
352 343
@@ -445,9 +436,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
445{ 436{
446 struct omap_mcpdm *mcpdm; 437 struct omap_mcpdm *mcpdm;
447 struct resource *res; 438 struct resource *res;
448 int ret = 0;
449 439
450 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); 440 mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL);
451 if (!mcpdm) 441 if (!mcpdm)
452 return -ENOMEM; 442 return -ENOMEM;
453 443
@@ -455,56 +445,54 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
455 445
456 mutex_init(&mcpdm->mutex); 446 mutex_init(&mcpdm->mutex);
457 447
448 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
449 if (res == NULL)
450 return -ENOMEM;
451
452 omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA;
453 omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA;
454
458 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 455 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
459 if (res == NULL) { 456 if (res == NULL)
460 dev_err(&pdev->dev, "no resource\n"); 457 return -ENOMEM;
461 goto err_res;
462 }
463 458
464 if (!request_mem_region(res->start, resource_size(res), "McPDM")) { 459 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link");
465 ret = -EBUSY; 460 if (!res)
466 goto err_res; 461 return -ENODEV;
467 }
468 462
469 mcpdm->io_base = ioremap(res->start, resource_size(res)); 463 omap_mcpdm_dai_dma_params[0].dma_req = res->start;
470 if (!mcpdm->io_base) { 464
471 ret = -ENOMEM; 465 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link");
472 goto err_iomap; 466 if (!res)
473 } 467 return -ENODEV;
468
469 omap_mcpdm_dai_dma_params[1].dma_req = res->start;
470
471 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
472 if (res == NULL)
473 return -ENOMEM;
474
475 if (!devm_request_mem_region(&pdev->dev, res->start,
476 resource_size(res), "McPDM"))
477 return -EBUSY;
478
479 mcpdm->io_base = devm_ioremap(&pdev->dev, res->start,
480 resource_size(res));
481 if (!mcpdm->io_base)
482 return -ENOMEM;
474 483
475 mcpdm->irq = platform_get_irq(pdev, 0); 484 mcpdm->irq = platform_get_irq(pdev, 0);
476 if (mcpdm->irq < 0) { 485 if (mcpdm->irq < 0)
477 ret = mcpdm->irq; 486 return mcpdm->irq;
478 goto err_irq;
479 }
480 487
481 mcpdm->dev = &pdev->dev; 488 mcpdm->dev = &pdev->dev;
482 489
483 ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); 490 return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
484 if (!ret)
485 return 0;
486
487err_irq:
488 iounmap(mcpdm->io_base);
489err_iomap:
490 release_mem_region(res->start, resource_size(res));
491err_res:
492 kfree(mcpdm);
493 return ret;
494} 491}
495 492
496static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) 493static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
497{ 494{
498 struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
499 struct resource *res;
500
501 snd_soc_unregister_dai(&pdev->dev); 495 snd_soc_unregister_dai(&pdev->dev);
502
503 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
504 iounmap(mcpdm->io_base);
505 release_mem_region(res->start, resource_size(res));
506
507 kfree(mcpdm);
508 return 0; 496 return 0;
509} 497}
510 498
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index f0feb06615f8..a2636f6b8362 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -25,12 +25,13 @@
25#include <linux/dma-mapping.h> 25#include <linux/dma-mapping.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/omap-dma.h>
28#include <sound/core.h> 29#include <sound/core.h>
29#include <sound/pcm.h> 30#include <sound/pcm.h>
30#include <sound/pcm_params.h> 31#include <sound/pcm_params.h>
32#include <sound/dmaengine_pcm.h>
31#include <sound/soc.h> 33#include <sound/soc.h>
32 34
33#include <plat/dma.h>
34#include "omap-pcm.h" 35#include "omap-pcm.h"
35 36
36static const struct snd_pcm_hardware omap_pcm_hardware = { 37static const struct snd_pcm_hardware omap_pcm_hardware = {
@@ -49,61 +50,34 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
49 .buffer_bytes_max = 128 * 1024, 50 .buffer_bytes_max = 128 * 1024,
50}; 51};
51 52
52struct omap_runtime_data { 53static int omap_pcm_get_dma_buswidth(int num_bits)
53 spinlock_t lock;
54 struct omap_pcm_dma_data *dma_data;
55 int dma_ch;
56 int period_index;
57};
58
59static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
60{ 54{
61 struct snd_pcm_substream *substream = data; 55 int buswidth;
62 struct snd_pcm_runtime *runtime = substream->runtime;
63 struct omap_runtime_data *prtd = runtime->private_data;
64 unsigned long flags;
65
66 if ((cpu_is_omap1510())) {
67 /*
68 * OMAP1510 doesn't fully support DMA progress counter
69 * and there is no software emulation implemented yet,
70 * so have to maintain our own progress counters
71 * that can be used by omap_pcm_pointer() instead.
72 */
73 spin_lock_irqsave(&prtd->lock, flags);
74 if ((stat == OMAP_DMA_LAST_IRQ) &&
75 (prtd->period_index == runtime->periods - 1)) {
76 /* we are in sync, do nothing */
77 spin_unlock_irqrestore(&prtd->lock, flags);
78 return;
79 }
80 if (prtd->period_index >= 0) {
81 if (stat & OMAP_DMA_BLOCK_IRQ) {
82 /* end of buffer reached, loop back */
83 prtd->period_index = 0;
84 } else if (stat & OMAP_DMA_LAST_IRQ) {
85 /* update the counter for the last period */
86 prtd->period_index = runtime->periods - 1;
87 } else if (++prtd->period_index >= runtime->periods) {
88 /* end of buffer missed? loop back */
89 prtd->period_index = 0;
90 }
91 }
92 spin_unlock_irqrestore(&prtd->lock, flags);
93 }
94 56
95 snd_pcm_period_elapsed(substream); 57 switch (num_bits) {
58 case 16:
59 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
60 break;
61 case 32:
62 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
63 break;
64 default:
65 buswidth = -EINVAL;
66 break;
67 }
68 return buswidth;
96} 69}
97 70
71
98/* this may get called several times by oss emulation */ 72/* this may get called several times by oss emulation */
99static int omap_pcm_hw_params(struct snd_pcm_substream *substream, 73static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
100 struct snd_pcm_hw_params *params) 74 struct snd_pcm_hw_params *params)
101{ 75{
102 struct snd_pcm_runtime *runtime = substream->runtime; 76 struct snd_pcm_runtime *runtime = substream->runtime;
103 struct snd_soc_pcm_runtime *rtd = substream->private_data; 77 struct snd_soc_pcm_runtime *rtd = substream->private_data;
104 struct omap_runtime_data *prtd = runtime->private_data;
105 struct omap_pcm_dma_data *dma_data; 78 struct omap_pcm_dma_data *dma_data;
106 79 struct dma_slave_config config;
80 struct dma_chan *chan;
107 int err = 0; 81 int err = 0;
108 82
109 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 83 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
@@ -116,162 +90,78 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
116 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 90 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
117 runtime->dma_bytes = params_buffer_bytes(params); 91 runtime->dma_bytes = params_buffer_bytes(params);
118 92
119 if (prtd->dma_data) 93 chan = snd_dmaengine_pcm_get_chan(substream);
120 return 0; 94 if (!chan)
121 prtd->dma_data = dma_data; 95 return -EINVAL;
122 err = omap_request_dma(dma_data->dma_req, dma_data->name,
123 omap_pcm_dma_irq, substream, &prtd->dma_ch);
124 if (!err) {
125 /*
126 * Link channel with itself so DMA doesn't need any
127 * reprogramming while looping the buffer
128 */
129 omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch);
130 }
131 96
132 return err; 97 /* fills in addr_width and direction */
133} 98 err = snd_hwparams_to_dma_slave_config(substream, params, &config);
99 if (err)
100 return err;
134 101
135static int omap_pcm_hw_free(struct snd_pcm_substream *substream) 102 /* Override the *_dma addr_width if requested by the DAI driver */
136{ 103 if (dma_data->data_type) {
137 struct snd_pcm_runtime *runtime = substream->runtime; 104 int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type);
138 struct omap_runtime_data *prtd = runtime->private_data;
139 105
140 if (prtd->dma_data == NULL) 106 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
141 return 0; 107 config.dst_addr_width = buswidth;
142 108 else
143 omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); 109 config.src_addr_width = buswidth;
144 omap_free_dma(prtd->dma_ch); 110 }
145 prtd->dma_data = NULL;
146 111
147 snd_pcm_set_runtime_buffer(substream, NULL); 112 config.src_addr = dma_data->port_addr;
113 config.dst_addr = dma_data->port_addr;
114 config.src_maxburst = dma_data->packet_size;
115 config.dst_maxburst = dma_data->packet_size;
148 116
149 return 0; 117 return dmaengine_slave_config(chan, &config);
150} 118}
151 119
152static int omap_pcm_prepare(struct snd_pcm_substream *substream) 120static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
153{ 121{
154 struct snd_pcm_runtime *runtime = substream->runtime; 122 snd_pcm_set_runtime_buffer(substream, NULL);
155 struct omap_runtime_data *prtd = runtime->private_data;
156 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
157 struct omap_dma_channel_params dma_params;
158 int bytes;
159
160 /* return if this is a bufferless transfer e.g.
161 * codec <--> BT codec or GSM modem -- lg FIXME */
162 if (!prtd->dma_data)
163 return 0;
164
165 memset(&dma_params, 0, sizeof(dma_params));
166 dma_params.data_type = dma_data->data_type;
167 dma_params.trigger = dma_data->dma_req;
168 dma_params.sync_mode = dma_data->sync_mode;
169 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
170 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
171 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
172 dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC;
173 dma_params.src_start = runtime->dma_addr;
174 dma_params.dst_start = dma_data->port_addr;
175 dma_params.dst_port = OMAP_DMA_PORT_MPUI;
176 dma_params.dst_fi = dma_data->packet_size;
177 } else {
178 dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
179 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
180 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
181 dma_params.src_start = dma_data->port_addr;
182 dma_params.dst_start = runtime->dma_addr;
183 dma_params.src_port = OMAP_DMA_PORT_MPUI;
184 dma_params.src_fi = dma_data->packet_size;
185 }
186 /*
187 * Set DMA transfer frame size equal to ALSA period size and frame
188 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
189 * we can transfer the whole ALSA buffer with single DMA transfer but
190 * still can get an interrupt at each period bounary
191 */
192 bytes = snd_pcm_lib_period_bytes(substream);
193 dma_params.elem_count = bytes >> dma_data->data_type;
194 dma_params.frame_count = runtime->periods;
195 omap_set_dma_params(prtd->dma_ch, &dma_params);
196
197 if ((cpu_is_omap1510()))
198 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
199 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
200 else if (!substream->runtime->no_period_wakeup)
201 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
202 else {
203 /*
204 * No period wakeup:
205 * we need to disable BLOCK_IRQ, which is enabled by the omap
206 * dma core at request dma time.
207 */
208 omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
209 }
210
211 if (!(cpu_class_is_omap1())) {
212 omap_set_dma_src_burst_mode(prtd->dma_ch,
213 OMAP_DMA_DATA_BURST_16);
214 omap_set_dma_dest_burst_mode(prtd->dma_ch,
215 OMAP_DMA_DATA_BURST_16);
216 }
217
218 return 0; 123 return 0;
219} 124}
220 125
221static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 126static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
222{ 127{
223 struct snd_pcm_runtime *runtime = substream->runtime; 128 struct snd_soc_pcm_runtime *rtd = substream->private_data;
224 struct omap_runtime_data *prtd = runtime->private_data; 129 struct omap_pcm_dma_data *dma_data;
225 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
226 unsigned long flags;
227 int ret = 0; 130 int ret = 0;
228 131
229 spin_lock_irqsave(&prtd->lock, flags); 132 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
133
230 switch (cmd) { 134 switch (cmd) {
231 case SNDRV_PCM_TRIGGER_START: 135 case SNDRV_PCM_TRIGGER_START:
232 case SNDRV_PCM_TRIGGER_RESUME: 136 case SNDRV_PCM_TRIGGER_RESUME:
233 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 137 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
234 prtd->period_index = 0;
235 /* Configure McBSP internal buffer usage */ 138 /* Configure McBSP internal buffer usage */
236 if (dma_data->set_threshold) 139 if (dma_data->set_threshold)
237 dma_data->set_threshold(substream); 140 dma_data->set_threshold(substream);
238
239 omap_start_dma(prtd->dma_ch);
240 break; 141 break;
241 142
242 case SNDRV_PCM_TRIGGER_STOP: 143 case SNDRV_PCM_TRIGGER_STOP:
243 case SNDRV_PCM_TRIGGER_SUSPEND: 144 case SNDRV_PCM_TRIGGER_SUSPEND:
244 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 145 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
245 prtd->period_index = -1;
246 omap_stop_dma(prtd->dma_ch);
247 break; 146 break;
248 default: 147 default:
249 ret = -EINVAL; 148 ret = -EINVAL;
250 } 149 }
251 spin_unlock_irqrestore(&prtd->lock, flags); 150
151 if (ret == 0)
152 ret = snd_dmaengine_pcm_trigger(substream, cmd);
252 153
253 return ret; 154 return ret;
254} 155}
255 156
256static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) 157static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
257{ 158{
258 struct snd_pcm_runtime *runtime = substream->runtime;
259 struct omap_runtime_data *prtd = runtime->private_data;
260 dma_addr_t ptr;
261 snd_pcm_uframes_t offset; 159 snd_pcm_uframes_t offset;
262 160
263 if (cpu_is_omap1510()) { 161 if (cpu_is_omap1510())
264 offset = prtd->period_index * runtime->period_size; 162 offset = snd_dmaengine_pcm_pointer_no_residue(substream);
265 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 163 else
266 ptr = omap_get_dma_dst_pos(prtd->dma_ch); 164 offset = snd_dmaengine_pcm_pointer(substream);
267 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
268 } else {
269 ptr = omap_get_dma_src_pos(prtd->dma_ch);
270 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
271 }
272
273 if (offset >= runtime->buffer_size)
274 offset = 0;
275 165
276 return offset; 166 return offset;
277} 167}
@@ -279,7 +169,8 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
279static int omap_pcm_open(struct snd_pcm_substream *substream) 169static int omap_pcm_open(struct snd_pcm_substream *substream)
280{ 170{
281 struct snd_pcm_runtime *runtime = substream->runtime; 171 struct snd_pcm_runtime *runtime = substream->runtime;
282 struct omap_runtime_data *prtd; 172 struct snd_soc_pcm_runtime *rtd = substream->private_data;
173 struct omap_pcm_dma_data *dma_data;
283 int ret; 174 int ret;
284 175
285 snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); 176 snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
@@ -288,25 +179,17 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
288 ret = snd_pcm_hw_constraint_integer(runtime, 179 ret = snd_pcm_hw_constraint_integer(runtime,
289 SNDRV_PCM_HW_PARAM_PERIODS); 180 SNDRV_PCM_HW_PARAM_PERIODS);
290 if (ret < 0) 181 if (ret < 0)
291 goto out; 182 return ret;
292 183
293 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 184 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
294 if (prtd == NULL) { 185 ret = snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
295 ret = -ENOMEM; 186 &dma_data->dma_req);
296 goto out;
297 }
298 spin_lock_init(&prtd->lock);
299 runtime->private_data = prtd;
300
301out:
302 return ret; 187 return ret;
303} 188}
304 189
305static int omap_pcm_close(struct snd_pcm_substream *substream) 190static int omap_pcm_close(struct snd_pcm_substream *substream)
306{ 191{
307 struct snd_pcm_runtime *runtime = substream->runtime; 192 snd_dmaengine_pcm_close(substream);
308
309 kfree(runtime->private_data);
310 return 0; 193 return 0;
311} 194}
312 195
@@ -327,7 +210,6 @@ static struct snd_pcm_ops omap_pcm_ops = {
327 .ioctl = snd_pcm_lib_ioctl, 210 .ioctl = snd_pcm_lib_ioctl,
328 .hw_params = omap_pcm_hw_params, 211 .hw_params = omap_pcm_hw_params,
329 .hw_free = omap_pcm_hw_free, 212 .hw_free = omap_pcm_hw_free,
330 .prepare = omap_pcm_prepare,
331 .trigger = omap_pcm_trigger, 213 .trigger = omap_pcm_trigger,
332 .pointer = omap_pcm_pointer, 214 .pointer = omap_pcm_pointer,
333 .mmap = omap_pcm_mmap, 215 .mmap = omap_pcm_mmap,
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index b92248cbd47a..cabe74c4068b 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -32,8 +32,8 @@ struct omap_pcm_dma_data {
32 int dma_req; /* DMA request line */ 32 int dma_req; /* DMA request line */
33 unsigned long port_addr; /* transmit/receive register */ 33 unsigned long port_addr; /* transmit/receive register */
34 void (*set_threshold)(struct snd_pcm_substream *substream); 34 void (*set_threshold)(struct snd_pcm_substream *substream);
35 int data_type; /* data type 8,16,32 */ 35 int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm
36 int sync_mode; /* DMA sync mode */ 36 * to decide the sDMA data type */
37 int packet_size; /* packet size only in PACKET mode */ 37 int packet_size; /* packet size only in PACKET mode */
38}; 38};
39 39
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
new file mode 100644
index 000000000000..3b97b87971f5
--- /dev/null
+++ b/sound/soc/omap/omap-twl4030.c
@@ -0,0 +1,188 @@
1/*
2 * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
5 * All rights reserved.
6 *
7 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
8 *
9 * This driver replaces the following machine drivers:
10 * omap3beagle (Author: Steve Sakoman <steve@sakoman.com>)
11 * omap3evm (Author: Anuj Aggarwal <anuj.aggarwal@ti.com>)
12 * overo (Author: Steve Sakoman <steve@sakoman.com>)
13 * igep0020 (Author: Enric Balletbo i Serra <eballetbo@iseebcn.com>)
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <linux/platform_device.h>
32#include <linux/platform_data/omap-twl4030.h>
33#include <linux/module.h>
34#include <linux/of.h>
35
36#include <sound/core.h>
37#include <sound/pcm.h>
38#include <sound/soc.h>
39
40#include "omap-mcbsp.h"
41#include "omap-pcm.h"
42
43static int omap_twl4030_hw_params(struct snd_pcm_substream *substream,
44 struct snd_pcm_hw_params *params)
45{
46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
47 struct snd_soc_dai *codec_dai = rtd->codec_dai;
48 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
49 struct snd_soc_codec *codec = rtd->codec;
50 struct snd_soc_card *card = codec->card;
51 unsigned int fmt;
52 int ret;
53
54 switch (params_channels(params)) {
55 case 2: /* Stereo I2S mode */
56 fmt = SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_NF |
58 SND_SOC_DAIFMT_CBM_CFM;
59 break;
60 case 4: /* Four channel TDM mode */
61 fmt = SND_SOC_DAIFMT_DSP_A |
62 SND_SOC_DAIFMT_IB_NF |
63 SND_SOC_DAIFMT_CBM_CFM;
64 break;
65 default:
66 return -EINVAL;
67 }
68
69 /* Set codec DAI configuration */
70 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
71 if (ret < 0) {
72 dev_err(card->dev, "can't set codec DAI configuration\n");
73 return ret;
74 }
75
76 /* Set cpu DAI configuration */
77 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
78 if (ret < 0) {
79 dev_err(card->dev, "can't set cpu DAI configuration\n");
80 return ret;
81 }
82
83 return 0;
84}
85
86static struct snd_soc_ops omap_twl4030_ops = {
87 .hw_params = omap_twl4030_hw_params,
88};
89
90/* Digital audio interface glue - connects codec <--> CPU */
91static struct snd_soc_dai_link omap_twl4030_dai_links[] = {
92 {
93 .name = "TWL4030",
94 .stream_name = "TWL4030",
95 .cpu_dai_name = "omap-mcbsp.2",
96 .codec_dai_name = "twl4030-hifi",
97 .platform_name = "omap-pcm-audio",
98 .codec_name = "twl4030-codec",
99 .ops = &omap_twl4030_ops,
100 },
101};
102
103/* Audio machine driver */
104static struct snd_soc_card omap_twl4030_card = {
105 .owner = THIS_MODULE,
106 .dai_link = omap_twl4030_dai_links,
107 .num_links = ARRAY_SIZE(omap_twl4030_dai_links),
108};
109
110static __devinit int omap_twl4030_probe(struct platform_device *pdev)
111{
112 struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev);
113 struct device_node *node = pdev->dev.of_node;
114 struct snd_soc_card *card = &omap_twl4030_card;
115 int ret = 0;
116
117 card->dev = &pdev->dev;
118
119 if (node) {
120 struct device_node *dai_node;
121
122 if (snd_soc_of_parse_card_name(card, "ti,model")) {
123 dev_err(&pdev->dev, "Card name is not provided\n");
124 return -ENODEV;
125 }
126
127 dai_node = of_parse_phandle(node, "ti,mcbsp", 0);
128 if (!dai_node) {
129 dev_err(&pdev->dev, "McBSP node is not provided\n");
130 return -EINVAL;
131 }
132 omap_twl4030_dai_links[0].cpu_dai_name = NULL;
133 omap_twl4030_dai_links[0].cpu_of_node = dai_node;
134
135 } else if (pdata) {
136 if (pdata->card_name) {
137 card->name = pdata->card_name;
138 } else {
139 dev_err(&pdev->dev, "Card name is not provided\n");
140 return -ENODEV;
141 }
142 } else {
143 dev_err(&pdev->dev, "Missing pdata\n");
144 return -ENODEV;
145 }
146
147 ret = snd_soc_register_card(card);
148 if (ret) {
149 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
150 ret);
151 return ret;
152 }
153
154 return 0;
155}
156
157static int __devexit omap_twl4030_remove(struct platform_device *pdev)
158{
159 struct snd_soc_card *card = platform_get_drvdata(pdev);
160
161 snd_soc_unregister_card(card);
162
163 return 0;
164}
165
166static const struct of_device_id omap_twl4030_of_match[] = {
167 {.compatible = "ti,omap-twl4030", },
168 { },
169};
170MODULE_DEVICE_TABLE(of, omap_twl4030_of_match);
171
172static struct platform_driver omap_twl4030_driver = {
173 .driver = {
174 .name = "omap-twl4030",
175 .owner = THIS_MODULE,
176 .pm = &snd_soc_pm_ops,
177 .of_match_table = omap_twl4030_of_match,
178 },
179 .probe = omap_twl4030_probe,
180 .remove = __devexit_p(omap_twl4030_remove),
181};
182
183module_platform_driver(omap_twl4030_driver);
184
185MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
186MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec");
187MODULE_LICENSE("GPL");
188MODULE_ALIAS("platform:omap-twl4030");
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
deleted file mode 100644
index 2830dfd05661..000000000000
--- a/sound/soc/omap/omap3beagle.c
+++ /dev/null
@@ -1,150 +0,0 @@
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 <linux/module.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/soc.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <plat/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36
37static int omap3beagle_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 unsigned int fmt;
44 int ret;
45
46 switch (params_channels(params)) {
47 case 2: /* Stereo I2S mode */
48 fmt = SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM;
51 break;
52 case 4: /* Four channel TDM mode */
53 fmt = SND_SOC_DAIFMT_DSP_A |
54 SND_SOC_DAIFMT_IB_NF |
55 SND_SOC_DAIFMT_CBM_CFM;
56 break;
57 default:
58 return -EINVAL;
59 }
60
61 /* Set codec DAI configuration */
62 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
63 if (ret < 0) {
64 printk(KERN_ERR "can't set codec DAI configuration\n");
65 return ret;
66 }
67
68 /* Set cpu DAI configuration */
69 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
70 if (ret < 0) {
71 printk(KERN_ERR "can't set cpu DAI configuration\n");
72 return ret;
73 }
74
75 /* Set the codec system clock for DAC and ADC */
76 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
77 SND_SOC_CLOCK_IN);
78 if (ret < 0) {
79 printk(KERN_ERR "can't set codec system clock\n");
80 return ret;
81 }
82
83 return 0;
84}
85
86static struct snd_soc_ops omap3beagle_ops = {
87 .hw_params = omap3beagle_hw_params,
88};
89
90/* Digital audio interface glue - connects codec <--> CPU */
91static struct snd_soc_dai_link omap3beagle_dai = {
92 .name = "TWL4030",
93 .stream_name = "TWL4030",
94 .cpu_dai_name = "omap-mcbsp.2",
95 .platform_name = "omap-pcm-audio",
96 .codec_dai_name = "twl4030-hifi",
97 .codec_name = "twl4030-codec",
98 .ops = &omap3beagle_ops,
99};
100
101/* Audio machine driver */
102static struct snd_soc_card snd_soc_omap3beagle = {
103 .name = "omap3beagle",
104 .owner = THIS_MODULE,
105 .dai_link = &omap3beagle_dai,
106 .num_links = 1,
107};
108
109static struct platform_device *omap3beagle_snd_device;
110
111static int __init omap3beagle_soc_init(void)
112{
113 int ret;
114
115 if (!(machine_is_omap3_beagle() || machine_is_devkit8000()))
116 return -ENODEV;
117 pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");
118
119 omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
120 if (!omap3beagle_snd_device) {
121 printk(KERN_ERR "Platform device allocation failed\n");
122 return -ENOMEM;
123 }
124
125 platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);
126
127 ret = platform_device_add(omap3beagle_snd_device);
128 if (ret)
129 goto err1;
130
131 return 0;
132
133err1:
134 printk(KERN_ERR "Unable to add platform device\n");
135 platform_device_put(omap3beagle_snd_device);
136
137 return ret;
138}
139
140static void __exit omap3beagle_soc_exit(void)
141{
142 platform_device_unregister(omap3beagle_snd_device);
143}
144
145module_init(omap3beagle_soc_init);
146module_exit(omap3beagle_soc_exit);
147
148MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
149MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
150MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
deleted file mode 100644
index 3d468c9179d7..000000000000
--- a/sound/soc/omap/omap3evm.c
+++ /dev/null
@@ -1,118 +0,0 @@
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 <linux/module.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/soc.h>
26
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include <mach/gpio.h>
30#include <plat/mcbsp.h>
31
32#include "omap-mcbsp.h"
33#include "omap-pcm.h"
34
35static int omap3evm_hw_params(struct snd_pcm_substream *substream,
36 struct snd_pcm_hw_params *params)
37{
38 struct snd_soc_pcm_runtime *rtd = substream->private_data;
39 struct snd_soc_dai *codec_dai = rtd->codec_dai;
40 int ret;
41
42 /* Set the codec system clock for DAC and ADC */
43 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
44 SND_SOC_CLOCK_IN);
45 if (ret < 0) {
46 printk(KERN_ERR "Can't set codec system clock\n");
47 return ret;
48 }
49
50 return 0;
51}
52
53static struct snd_soc_ops omap3evm_ops = {
54 .hw_params = omap3evm_hw_params,
55};
56
57/* Digital audio interface glue - connects codec <--> CPU */
58static struct snd_soc_dai_link omap3evm_dai = {
59 .name = "TWL4030",
60 .stream_name = "TWL4030",
61 .cpu_dai_name = "omap-mcbsp.2",
62 .codec_dai_name = "twl4030-hifi",
63 .platform_name = "omap-pcm-audio",
64 .codec_name = "twl4030-codec",
65 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
66 SND_SOC_DAIFMT_CBM_CFM,
67 .ops = &omap3evm_ops,
68};
69
70/* Audio machine driver */
71static struct snd_soc_card snd_soc_omap3evm = {
72 .name = "omap3evm",
73 .owner = THIS_MODULE,
74 .dai_link = &omap3evm_dai,
75 .num_links = 1,
76};
77
78static struct platform_device *omap3evm_snd_device;
79
80static int __init omap3evm_soc_init(void)
81{
82 int ret;
83
84 if (!machine_is_omap3evm())
85 return -ENODEV;
86 pr_info("OMAP3 EVM SoC init\n");
87
88 omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
89 if (!omap3evm_snd_device) {
90 printk(KERN_ERR "Platform device allocation failed\n");
91 return -ENOMEM;
92 }
93
94 platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);
95 ret = platform_device_add(omap3evm_snd_device);
96 if (ret)
97 goto err1;
98
99 return 0;
100
101err1:
102 printk(KERN_ERR "Unable to add platform device\n");
103 platform_device_put(omap3evm_snd_device);
104
105 return ret;
106}
107
108static void __exit omap3evm_soc_exit(void)
109{
110 platform_device_unregister(omap3evm_snd_device);
111}
112
113module_init(omap3evm_soc_init);
114module_exit(omap3evm_soc_exit);
115
116MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
117MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
118MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
deleted file mode 100644
index 6ac3e0c3c282..000000000000
--- a/sound/soc/omap/overo.c
+++ /dev/null
@@ -1,122 +0,0 @@
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 <linux/module.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/soc.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <plat/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36
37static int overo_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 int ret;
43
44 /* Set the codec system clock for DAC and ADC */
45 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
46 SND_SOC_CLOCK_IN);
47 if (ret < 0) {
48 printk(KERN_ERR "can't set codec system clock\n");
49 return ret;
50 }
51
52 return 0;
53}
54
55static struct snd_soc_ops overo_ops = {
56 .hw_params = overo_hw_params,
57};
58
59/* Digital audio interface glue - connects codec <--> CPU */
60static struct snd_soc_dai_link overo_dai = {
61 .name = "TWL4030",
62 .stream_name = "TWL4030",
63 .cpu_dai_name = "omap-mcbsp.2",
64 .codec_dai_name = "twl4030-hifi",
65 .platform_name = "omap-pcm-audio",
66 .codec_name = "twl4030-codec",
67 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
68 SND_SOC_DAIFMT_CBM_CFM,
69 .ops = &overo_ops,
70};
71
72/* Audio machine driver */
73static struct snd_soc_card snd_soc_card_overo = {
74 .name = "overo",
75 .owner = THIS_MODULE,
76 .dai_link = &overo_dai,
77 .num_links = 1,
78};
79
80static struct platform_device *overo_snd_device;
81
82static int __init overo_soc_init(void)
83{
84 int ret;
85
86 if (!(machine_is_overo() || machine_is_cm_t35())) {
87 pr_debug("Incomatible machine!\n");
88 return -ENODEV;
89 }
90 printk(KERN_INFO "overo SoC init\n");
91
92 overo_snd_device = platform_device_alloc("soc-audio", -1);
93 if (!overo_snd_device) {
94 printk(KERN_ERR "Platform device allocation failed\n");
95 return -ENOMEM;
96 }
97
98 platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);
99
100 ret = platform_device_add(overo_snd_device);
101 if (ret)
102 goto err1;
103
104 return 0;
105
106err1:
107 printk(KERN_ERR "Unable to add platform device\n");
108 platform_device_put(overo_snd_device);
109
110 return ret;
111}
112module_init(overo_soc_init);
113
114static void __exit overo_soc_exit(void)
115{
116 platform_device_unregister(overo_snd_device);
117}
118module_exit(overo_soc_exit);
119
120MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
121MODULE_DESCRIPTION("ALSA SoC overo");
122MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 920e0d9e03db..df97a4196cd3 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -191,9 +191,6 @@ static int __init zoom2_soc_init(void)
191 BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); 191 BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
192 gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); 192 gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
193 193
194 BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0);
195 gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0);
196
197 return 0; 194 return 0;
198 195
199err1: 196err1:
@@ -207,7 +204,6 @@ module_init(zoom2_soc_init);
207static void __exit zoom2_soc_exit(void) 204static void __exit zoom2_soc_exit(void)
208{ 205{
209 gpio_free(ZOOM2_HEADSET_MUX_GPIO); 206 gpio_free(ZOOM2_HEADSET_MUX_GPIO);
210 gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO);
211 207
212 platform_device_unregister(zoom2_snd_device); 208 platform_device_unregister(zoom2_snd_device);
213} 209}