diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /sound/soc/omap | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'sound/soc/omap')
-rw-r--r-- | sound/soc/omap/Kconfig | 34 | ||||
-rw-r--r-- | sound/soc/omap/Makefile | 10 | ||||
-rw-r--r-- | sound/soc/omap/am3517evm.c | 202 | ||||
-rw-r--r-- | sound/soc/omap/ams-delta.c | 8 | ||||
-rw-r--r-- | sound/soc/omap/igep0020.c | 148 | ||||
-rw-r--r-- | sound/soc/omap/mcpdm.c | 485 | ||||
-rw-r--r-- | sound/soc/omap/mcpdm.h | 151 | ||||
-rw-r--r-- | sound/soc/omap/n810.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 219 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.h | 4 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcpdm.c | 252 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcpdm.h | 29 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 39 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.h | 4 | ||||
-rw-r--r-- | sound/soc/omap/omap2evm.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap3beagle.c | 8 | ||||
-rw-r--r-- | sound/soc/omap/omap3evm.c | 9 | ||||
-rw-r--r-- | sound/soc/omap/omap3pandora.c | 67 | ||||
-rw-r--r-- | sound/soc/omap/osk5912.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/overo.c | 6 | ||||
-rw-r--r-- | sound/soc/omap/sdp3430.c | 8 | ||||
-rw-r--r-- | sound/soc/omap/zoom2.c | 2 |
22 files changed, 1591 insertions, 100 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 653a362425df..f11963c21873 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -6,6 +6,9 @@ config SND_OMAP_SOC_MCBSP | |||
6 | tristate | 6 | tristate |
7 | select OMAP_MCBSP | 7 | select OMAP_MCBSP |
8 | 8 | ||
9 | config SND_OMAP_SOC_MCPDM | ||
10 | tristate | ||
11 | |||
9 | config SND_OMAP_SOC_N810 | 12 | config SND_OMAP_SOC_N810 |
10 | tristate "SoC Audio support for Nokia N810" | 13 | tristate "SoC Audio support for Nokia N810" |
11 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C | 14 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C |
@@ -43,12 +46,13 @@ config SND_OMAP_SOC_OSK5912 | |||
43 | Say Y if you want to add support for SoC audio on osk5912. | 46 | Say Y if you want to add support for SoC audio on osk5912. |
44 | 47 | ||
45 | config SND_OMAP_SOC_OVERO | 48 | config SND_OMAP_SOC_OVERO |
46 | tristate "SoC Audio support for Gumstix Overo" | 49 | tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" |
47 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO | 50 | depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) |
48 | select SND_OMAP_SOC_MCBSP | 51 | select SND_OMAP_SOC_MCBSP |
49 | select SND_SOC_TWL4030 | 52 | select SND_SOC_TWL4030 |
50 | help | 53 | help |
51 | Say Y if you want to add support for SoC audio on the Gumstix Overo. | 54 | Say Y if you want to add support for SoC audio on the |
55 | Gumstix Overo or CompuLab CM-T35 | ||
52 | 56 | ||
53 | config SND_OMAP_SOC_OMAP2EVM | 57 | config SND_OMAP_SOC_OMAP2EVM |
54 | tristate "SoC Audio support for OMAP2EVM board" | 58 | tristate "SoC Audio support for OMAP2EVM board" |
@@ -66,6 +70,15 @@ config SND_OMAP_SOC_OMAP3EVM | |||
66 | help | 70 | help |
67 | Say Y if you want to add support for SoC audio on the omap3evm board. | 71 | Say Y if you want to add support for SoC audio on the omap3evm board. |
68 | 72 | ||
73 | config SND_OMAP_SOC_AM3517EVM | ||
74 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" | ||
75 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C | ||
76 | select SND_OMAP_SOC_MCBSP | ||
77 | select SND_SOC_TLV320AIC23 | ||
78 | help | ||
79 | Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 | ||
80 | EVM. | ||
81 | |||
69 | config SND_OMAP_SOC_SDP3430 | 82 | config SND_OMAP_SOC_SDP3430 |
70 | tristate "SoC Audio support for Texas Instruments SDP3430" | 83 | tristate "SoC Audio support for Texas Instruments SDP3430" |
71 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP | 84 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP |
@@ -84,12 +97,14 @@ config SND_OMAP_SOC_OMAP3_PANDORA | |||
84 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. | 97 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. |
85 | 98 | ||
86 | config SND_OMAP_SOC_OMAP3_BEAGLE | 99 | config SND_OMAP_SOC_OMAP3_BEAGLE |
87 | tristate "SoC Audio support for OMAP3 Beagle" | 100 | tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" |
88 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE | 101 | depends on TWL4030_CORE && SND_OMAP_SOC |
102 | depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) | ||
89 | select SND_OMAP_SOC_MCBSP | 103 | select SND_OMAP_SOC_MCBSP |
90 | select SND_SOC_TWL4030 | 104 | select SND_SOC_TWL4030 |
91 | help | 105 | help |
92 | Say Y if you want to add support for SoC audio on the Beagleboard. | 106 | Say Y if you want to add support for SoC audio on the Beagleboard or |
107 | the clone Devkit8000. | ||
93 | 108 | ||
94 | config SND_OMAP_SOC_ZOOM2 | 109 | config SND_OMAP_SOC_ZOOM2 |
95 | tristate "SoC Audio support for Zoom2" | 110 | tristate "SoC Audio support for Zoom2" |
@@ -99,3 +114,10 @@ config SND_OMAP_SOC_ZOOM2 | |||
99 | help | 114 | help |
100 | Say Y if you want to add support for Soc audio on Zoom2 board. | 115 | Say Y if you want to add support for Soc audio on Zoom2 board. |
101 | 116 | ||
117 | config SND_OMAP_SOC_IGEP0020 | ||
118 | tristate "SoC Audio support for IGEP v2" | ||
119 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 | ||
120 | select SND_OMAP_SOC_MCBSP | ||
121 | select SND_SOC_TWL4030 | ||
122 | help | ||
123 | 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 02d69471dcb5..0bc00ca14b37 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -1,9 +1,11 @@ | |||
1 | # OMAP Platform Support | 1 | # OMAP Platform Support |
2 | snd-soc-omap-objs := omap-pcm.o | 2 | snd-soc-omap-objs := omap-pcm.o |
3 | snd-soc-omap-mcbsp-objs := omap-mcbsp.o | 3 | snd-soc-omap-mcbsp-objs := omap-mcbsp.o |
4 | snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o | 6 | obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o |
6 | obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o | 7 | obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o |
8 | obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o | ||
7 | 9 | ||
8 | # OMAP Machine Support | 10 | # OMAP Machine Support |
9 | snd-soc-n810-objs := n810.o | 11 | snd-soc-n810-objs := n810.o |
@@ -12,18 +14,22 @@ snd-soc-osk5912-objs := osk5912.o | |||
12 | snd-soc-overo-objs := overo.o | 14 | snd-soc-overo-objs := overo.o |
13 | snd-soc-omap2evm-objs := omap2evm.o | 15 | snd-soc-omap2evm-objs := omap2evm.o |
14 | snd-soc-omap3evm-objs := omap3evm.o | 16 | snd-soc-omap3evm-objs := omap3evm.o |
17 | snd-soc-am3517evm-objs := am3517evm.o | ||
15 | snd-soc-sdp3430-objs := sdp3430.o | 18 | snd-soc-sdp3430-objs := sdp3430.o |
16 | snd-soc-omap3pandora-objs := omap3pandora.o | 19 | snd-soc-omap3pandora-objs := omap3pandora.o |
17 | snd-soc-omap3beagle-objs := omap3beagle.o | 20 | snd-soc-omap3beagle-objs := omap3beagle.o |
18 | snd-soc-zoom2-objs := zoom2.o | 21 | snd-soc-zoom2-objs := zoom2.o |
22 | snd-soc-igep0020-objs := igep0020.o | ||
19 | 23 | ||
20 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 24 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
21 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 25 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
22 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 26 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
23 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o |
24 | obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o |
25 | obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o |
30 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o | ||
26 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o | 31 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o |
27 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o | 32 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o |
28 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o | 33 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o |
29 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o | 34 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o |
35 | obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o | ||
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c new file mode 100644 index 000000000000..135901b2ea11 --- /dev/null +++ b/sound/soc/omap/am3517evm.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * am3517evm.c -- ALSA SoC support for OMAP3517 / AM3517 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) 2009 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 | #include <sound/soc-dapm.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 | |||
35 | #include "../codecs/tlv320aic23.h" | ||
36 | |||
37 | #define CODEC_CLOCK 12000000 | ||
38 | |||
39 | static int am3517evm_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->dai->codec_dai; | ||
44 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
45 | int ret; | ||
46 | |||
47 | /* Set codec DAI configuration */ | ||
48 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
49 | SND_SOC_DAIFMT_DSP_B | | ||
50 | SND_SOC_DAIFMT_NB_NF | | ||
51 | SND_SOC_DAIFMT_CBM_CFM); | ||
52 | if (ret < 0) { | ||
53 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | /* Set cpu DAI configuration */ | ||
58 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
59 | SND_SOC_DAIFMT_DSP_B | | ||
60 | SND_SOC_DAIFMT_NB_NF | | ||
61 | SND_SOC_DAIFMT_CBM_CFM); | ||
62 | if (ret < 0) { | ||
63 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | /* Set the codec system clock for DAC and ADC */ | ||
68 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | ||
69 | CODEC_CLOCK, SND_SOC_CLOCK_IN); | ||
70 | if (ret < 0) { | ||
71 | printk(KERN_ERR "can't set codec system clock\n"); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, | ||
76 | SND_SOC_CLOCK_IN); | ||
77 | if (ret < 0) { | ||
78 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, | ||
83 | SND_SOC_CLOCK_IN); | ||
84 | if (ret < 0) { | ||
85 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static struct snd_soc_ops am3517evm_ops = { | ||
93 | .hw_params = am3517evm_hw_params, | ||
94 | }; | ||
95 | |||
96 | /* am3517evm machine dapm widgets */ | ||
97 | static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { | ||
98 | SND_SOC_DAPM_HP("Line Out", NULL), | ||
99 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
100 | SND_SOC_DAPM_MIC("Mic In", NULL), | ||
101 | }; | ||
102 | |||
103 | static const struct snd_soc_dapm_route audio_map[] = { | ||
104 | /* Line Out connected to LLOUT, RLOUT */ | ||
105 | {"Line Out", NULL, "LOUT"}, | ||
106 | {"Line Out", NULL, "ROUT"}, | ||
107 | |||
108 | {"LLINEIN", NULL, "Line In"}, | ||
109 | {"RLINEIN", NULL, "Line In"}, | ||
110 | |||
111 | {"MICIN", NULL, "Mic In"}, | ||
112 | }; | ||
113 | |||
114 | static int am3517evm_aic23_init(struct snd_soc_codec *codec) | ||
115 | { | ||
116 | /* Add am3517-evm specific widgets */ | ||
117 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | ||
118 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); | ||
119 | |||
120 | /* Set up davinci-evm specific audio path audio_map */ | ||
121 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
122 | |||
123 | /* always connected */ | ||
124 | snd_soc_dapm_enable_pin(codec, "Line Out"); | ||
125 | snd_soc_dapm_enable_pin(codec, "Line In"); | ||
126 | snd_soc_dapm_enable_pin(codec, "Mic In"); | ||
127 | |||
128 | snd_soc_dapm_sync(codec); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
134 | static struct snd_soc_dai_link am3517evm_dai = { | ||
135 | .name = "TLV320AIC23", | ||
136 | .stream_name = "AIC23", | ||
137 | .cpu_dai = &omap_mcbsp_dai[0], | ||
138 | .codec_dai = &tlv320aic23_dai, | ||
139 | .init = am3517evm_aic23_init, | ||
140 | .ops = &am3517evm_ops, | ||
141 | }; | ||
142 | |||
143 | /* Audio machine driver */ | ||
144 | static struct snd_soc_card snd_soc_am3517evm = { | ||
145 | .name = "am3517evm", | ||
146 | .platform = &omap_soc_platform, | ||
147 | .dai_link = &am3517evm_dai, | ||
148 | .num_links = 1, | ||
149 | }; | ||
150 | |||
151 | /* Audio subsystem */ | ||
152 | static struct snd_soc_device am3517evm_snd_devdata = { | ||
153 | .card = &snd_soc_am3517evm, | ||
154 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
155 | }; | ||
156 | |||
157 | static struct platform_device *am3517evm_snd_device; | ||
158 | |||
159 | static int __init am3517evm_soc_init(void) | ||
160 | { | ||
161 | int ret; | ||
162 | |||
163 | if (!machine_is_omap3517evm()) { | ||
164 | pr_err("Not OMAP3517 / AM3517 EVM!\n"); | ||
165 | return -ENODEV; | ||
166 | } | ||
167 | pr_info("OMAP3517 / AM3517 EVM SoC init\n"); | ||
168 | |||
169 | am3517evm_snd_device = platform_device_alloc("soc-audio", -1); | ||
170 | if (!am3517evm_snd_device) { | ||
171 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | |||
175 | platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata); | ||
176 | am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev; | ||
177 | *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */ | ||
178 | |||
179 | ret = platform_device_add(am3517evm_snd_device); | ||
180 | if (ret) | ||
181 | goto err1; | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | err1: | ||
186 | printk(KERN_ERR "Unable to add platform device\n"); | ||
187 | platform_device_put(am3517evm_snd_device); | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static void __exit am3517evm_soc_exit(void) | ||
193 | { | ||
194 | platform_device_unregister(am3517evm_snd_device); | ||
195 | } | ||
196 | |||
197 | module_init(am3517evm_soc_init); | ||
198 | module_exit(am3517evm_soc_exit); | ||
199 | |||
200 | MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>"); | ||
201 | MODULE_DESCRIPTION("ALSA SoC OMAP3517 / AM3517 EVM"); | ||
202 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 5a5166ac7279..b0f618e44840 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -31,8 +31,8 @@ | |||
31 | 31 | ||
32 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
33 | 33 | ||
34 | #include <mach/board-ams-delta.h> | 34 | #include <plat/board-ams-delta.h> |
35 | #include <mach/mcbsp.h> | 35 | #include <plat/mcbsp.h> |
36 | 36 | ||
37 | #include "omap-mcbsp.h" | 37 | #include "omap-mcbsp.h" |
38 | #include "omap-pcm.h" | 38 | #include "omap-pcm.h" |
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | 41 | ||
42 | /* Board specific DAPM widgets */ | 42 | /* Board specific DAPM widgets */ |
43 | const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { | 43 | static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { |
44 | /* Handset */ | 44 | /* Handset */ |
45 | SND_SOC_DAPM_MIC("Mouthpiece", NULL), | 45 | SND_SOC_DAPM_MIC("Mouthpiece", NULL), |
46 | SND_SOC_DAPM_HP("Earpiece", NULL), | 46 | SND_SOC_DAPM_HP("Earpiece", NULL), |
@@ -81,7 +81,7 @@ static const char *ams_delta_audio_mode[] = | |||
81 | (1 << AMS_DELTA_SPEAKER)) | 81 | (1 << AMS_DELTA_SPEAKER)) |
82 | #define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) | 82 | #define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) |
83 | 83 | ||
84 | unsigned short ams_delta_audio_mode_pins[] = { | 84 | static const unsigned short ams_delta_audio_mode_pins[] = { |
85 | AMS_DELTA_MIXED, | 85 | AMS_DELTA_MIXED, |
86 | AMS_DELTA_HANDSET, | 86 | AMS_DELTA_HANDSET, |
87 | AMS_DELTA_HANDSFREE, | 87 | AMS_DELTA_HANDSFREE, |
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c new file mode 100644 index 000000000000..3583c429f9be --- /dev/null +++ b/sound/soc/omap/igep0020.c | |||
@@ -0,0 +1,148 @@ | |||
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 | #include <sound/soc-dapm.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 | #include "../codecs/twl4030.h" | ||
37 | |||
38 | static int igep2_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
44 | int ret; | ||
45 | |||
46 | /* Set codec DAI configuration */ | ||
47 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
48 | SND_SOC_DAIFMT_I2S | | ||
49 | SND_SOC_DAIFMT_NB_NF | | ||
50 | SND_SOC_DAIFMT_CBM_CFM); | ||
51 | if (ret < 0) { | ||
52 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | /* Set cpu DAI configuration */ | ||
57 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
58 | SND_SOC_DAIFMT_I2S | | ||
59 | SND_SOC_DAIFMT_NB_NF | | ||
60 | SND_SOC_DAIFMT_CBM_CFM); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | /* Set the codec system clock for DAC and ADC */ | ||
67 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
68 | SND_SOC_CLOCK_IN); | ||
69 | if (ret < 0) { | ||
70 | printk(KERN_ERR "can't set codec system clock\n"); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_ops igep2_ops = { | ||
78 | .hw_params = igep2_hw_params, | ||
79 | }; | ||
80 | |||
81 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
82 | static struct snd_soc_dai_link igep2_dai = { | ||
83 | .name = "TWL4030", | ||
84 | .stream_name = "TWL4030", | ||
85 | .cpu_dai = &omap_mcbsp_dai[0], | ||
86 | .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], | ||
87 | .ops = &igep2_ops, | ||
88 | }; | ||
89 | |||
90 | /* Audio machine driver */ | ||
91 | static struct snd_soc_card snd_soc_card_igep2 = { | ||
92 | .name = "igep2", | ||
93 | .platform = &omap_soc_platform, | ||
94 | .dai_link = &igep2_dai, | ||
95 | .num_links = 1, | ||
96 | }; | ||
97 | |||
98 | /* Audio subsystem */ | ||
99 | static struct snd_soc_device igep2_snd_devdata = { | ||
100 | .card = &snd_soc_card_igep2, | ||
101 | .codec_dev = &soc_codec_dev_twl4030, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device *igep2_snd_device; | ||
105 | |||
106 | static int __init igep2_soc_init(void) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | if (!machine_is_igep0020()) { | ||
111 | pr_debug("Not IGEP v2!\n"); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | printk(KERN_INFO "IGEP v2 SoC init\n"); | ||
115 | |||
116 | igep2_snd_device = platform_device_alloc("soc-audio", -1); | ||
117 | if (!igep2_snd_device) { | ||
118 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
119 | return -ENOMEM; | ||
120 | } | ||
121 | |||
122 | platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata); | ||
123 | igep2_snd_devdata.dev = &igep2_snd_device->dev; | ||
124 | *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
125 | |||
126 | ret = platform_device_add(igep2_snd_device); | ||
127 | if (ret) | ||
128 | goto err1; | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err1: | ||
133 | printk(KERN_ERR "Unable to add platform device\n"); | ||
134 | platform_device_put(igep2_snd_device); | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | module_init(igep2_soc_init); | ||
139 | |||
140 | static void __exit igep2_soc_exit(void) | ||
141 | { | ||
142 | platform_device_unregister(igep2_snd_device); | ||
143 | } | ||
144 | module_exit(igep2_soc_exit); | ||
145 | |||
146 | MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>"); | ||
147 | MODULE_DESCRIPTION("ALSA SoC IGEP v2"); | ||
148 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c new file mode 100644 index 000000000000..1dab4c14874d --- /dev/null +++ b/sound/soc/omap/mcpdm.c | |||
@@ -0,0 +1,485 @@ | |||
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 | |||
38 | static struct omap_mcpdm *mcpdm; | ||
39 | |||
40 | static inline void omap_mcpdm_write(u16 reg, u32 val) | ||
41 | { | ||
42 | __raw_writel(val, mcpdm->io_base + reg); | ||
43 | } | ||
44 | |||
45 | static inline int omap_mcpdm_read(u16 reg) | ||
46 | { | ||
47 | return __raw_readl(mcpdm->io_base + reg); | ||
48 | } | ||
49 | |||
50 | static 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 | */ | ||
88 | static 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 | |||
100 | static 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 | */ | ||
116 | void 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 | */ | ||
132 | void 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 | */ | ||
148 | int 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 | */ | ||
188 | int 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 | */ | ||
228 | int 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 | */ | ||
254 | int 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 | |||
276 | static 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 | |||
325 | int 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 | |||
355 | err: | ||
356 | clk_disable(mcpdm->clk); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | void 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 | */ | ||
379 | int 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 | |||
405 | static int __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 | |||
444 | err_clk: | ||
445 | iounmap(mcpdm->io_base); | ||
446 | err_resource: | ||
447 | kfree(mcpdm); | ||
448 | exit: | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static int __devexit 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 | |||
471 | static struct platform_driver omap_mcpdm_driver = { | ||
472 | .probe = omap_mcpdm_probe, | ||
473 | .remove = __devexit_p(omap_mcpdm_remove), | ||
474 | .driver = { | ||
475 | .name = "omap-mcpdm", | ||
476 | }, | ||
477 | }; | ||
478 | |||
479 | static struct platform_device *omap_mcpdm_device; | ||
480 | |||
481 | static int __init omap_mcpdm_init(void) | ||
482 | { | ||
483 | return platform_driver_register(&omap_mcpdm_driver); | ||
484 | } | ||
485 | arch_initcall(omap_mcpdm_init); | ||
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h new file mode 100644 index 000000000000..7bb326ef0886 --- /dev/null +++ b/sound/soc/omap/mcpdm.h | |||
@@ -0,0 +1,151 @@ | |||
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 | |||
113 | struct omap_mcpdm_link { | ||
114 | int irq_mask; | ||
115 | int threshold; | ||
116 | int format; | ||
117 | int channels; | ||
118 | }; | ||
119 | |||
120 | struct omap_mcpdm_platform_data { | ||
121 | unsigned long phys_base; | ||
122 | u16 irq; | ||
123 | }; | ||
124 | |||
125 | struct 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 | |||
143 | extern void omap_mcpdm_start(int stream); | ||
144 | extern void omap_mcpdm_stop(int stream); | ||
145 | extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink); | ||
146 | extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink); | ||
147 | extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink); | ||
148 | extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink); | ||
149 | extern int omap_mcpdm_request(void); | ||
150 | extern void omap_mcpdm_free(void); | ||
151 | extern int omap_mcpdm_set_offset(int offset1, int offset2); | ||
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 0a505938e42b..08e09d72790f 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
33 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
35 | #include <mach/mcbsp.h> | 35 | #include <plat/mcbsp.h> |
36 | 36 | ||
37 | #include "omap-mcbsp.h" | 37 | #include "omap-mcbsp.h" |
38 | #include "omap-pcm.h" | 38 | #include "omap-pcm.h" |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 3341f49402ca..8ad9dc901007 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -31,14 +31,22 @@ | |||
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
33 | 33 | ||
34 | #include <mach/control.h> | 34 | #include <plat/control.h> |
35 | #include <mach/dma.h> | 35 | #include <plat/dma.h> |
36 | #include <mach/mcbsp.h> | 36 | #include <plat/mcbsp.h> |
37 | #include "omap-mcbsp.h" | 37 | #include "omap-mcbsp.h" |
38 | #include "omap-pcm.h" | 38 | #include "omap-pcm.h" |
39 | 39 | ||
40 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) | 40 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) |
41 | 41 | ||
42 | #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \ | ||
43 | xhandler_get, xhandler_put) \ | ||
44 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
45 | .info = omap_mcbsp_st_info_volsw, \ | ||
46 | .get = xhandler_get, .put = xhandler_put, \ | ||
47 | .private_value = (unsigned long) &(struct soc_mixer_control) \ | ||
48 | {.min = xmin, .max = xmax} } | ||
49 | |||
42 | struct omap_mcbsp_data { | 50 | struct omap_mcbsp_data { |
43 | unsigned int bus_id; | 51 | unsigned int bus_id; |
44 | struct omap_mcbsp_reg_cfg regs; | 52 | struct omap_mcbsp_reg_cfg regs; |
@@ -49,6 +57,8 @@ struct omap_mcbsp_data { | |||
49 | */ | 57 | */ |
50 | int active; | 58 | int active; |
51 | int configured; | 59 | int configured; |
60 | unsigned int in_freq; | ||
61 | int clk_div; | ||
52 | }; | 62 | }; |
53 | 63 | ||
54 | #define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) | 64 | #define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) |
@@ -80,11 +90,11 @@ static const int omap1_dma_reqs[][2] = {}; | |||
80 | static const unsigned long omap1_mcbsp_port[][2] = {}; | 90 | static const unsigned long omap1_mcbsp_port[][2] = {}; |
81 | #endif | 91 | #endif |
82 | 92 | ||
83 | #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) | 93 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
84 | static const int omap24xx_dma_reqs[][2] = { | 94 | static const int omap24xx_dma_reqs[][2] = { |
85 | { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, | 95 | { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, |
86 | { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, | 96 | { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, |
87 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | 97 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
88 | { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX }, | 98 | { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX }, |
89 | { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX }, | 99 | { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX }, |
90 | { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX }, | 100 | { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX }, |
@@ -122,7 +132,7 @@ static const unsigned long omap2430_mcbsp_port[][2] = { | |||
122 | static const unsigned long omap2430_mcbsp_port[][2] = {}; | 132 | static const unsigned long omap2430_mcbsp_port[][2] = {}; |
123 | #endif | 133 | #endif |
124 | 134 | ||
125 | #if defined(CONFIG_ARCH_OMAP34XX) | 135 | #if defined(CONFIG_ARCH_OMAP3) |
126 | static const unsigned long omap34xx_mcbsp_port[][2] = { | 136 | static const unsigned long omap34xx_mcbsp_port[][2] = { |
127 | { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, | 137 | { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, |
128 | OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, | 138 | OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, |
@@ -257,7 +267,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
257 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; | 267 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; |
258 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; | 268 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; |
259 | unsigned long port; | 269 | unsigned long port; |
260 | unsigned int format; | 270 | unsigned int format, div, framesize, master; |
261 | 271 | ||
262 | if (cpu_class_is_omap1()) { | 272 | if (cpu_class_is_omap1()) { |
263 | dma = omap1_dma_reqs[bus_id][substream->stream]; | 273 | dma = omap1_dma_reqs[bus_id][substream->stream]; |
@@ -285,7 +295,11 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
285 | omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; | 295 | omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; |
286 | omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; | 296 | omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; |
287 | omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; | 297 | omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; |
288 | cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; | 298 | omap_mcbsp_dai_dma_params[id][substream->stream].data_type = |
299 | OMAP_DMA_DATA_TYPE_S16; | ||
300 | |||
301 | snd_soc_dai_set_dma_data(cpu_dai, substream, | ||
302 | &omap_mcbsp_dai_dma_params[id][substream->stream]); | ||
289 | 303 | ||
290 | if (mcbsp_data->configured) { | 304 | if (mcbsp_data->configured) { |
291 | /* McBSP already configured by another stream */ | 305 | /* McBSP already configured by another stream */ |
@@ -294,28 +308,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
294 | 308 | ||
295 | format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; | 309 | format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
296 | wpf = channels = params_channels(params); | 310 | wpf = channels = params_channels(params); |
297 | switch (channels) { | 311 | if (channels == 2 && format == SND_SOC_DAIFMT_I2S) { |
298 | case 2: | 312 | /* Use dual-phase frames */ |
299 | if (format == SND_SOC_DAIFMT_I2S) { | 313 | regs->rcr2 |= RPHASE; |
300 | /* Use dual-phase frames */ | 314 | regs->xcr2 |= XPHASE; |
301 | regs->rcr2 |= RPHASE; | 315 | /* Set 1 word per (McBSP) frame for phase1 and phase2 */ |
302 | regs->xcr2 |= XPHASE; | 316 | wpf--; |
303 | /* Set 1 word per (McBSP) frame for phase1 and phase2 */ | 317 | regs->rcr2 |= RFRLEN2(wpf - 1); |
304 | wpf--; | 318 | regs->xcr2 |= XFRLEN2(wpf - 1); |
305 | regs->rcr2 |= RFRLEN2(wpf - 1); | ||
306 | regs->xcr2 |= XFRLEN2(wpf - 1); | ||
307 | } | ||
308 | case 1: | ||
309 | case 4: | ||
310 | /* Set word per (McBSP) frame for phase1 */ | ||
311 | regs->rcr1 |= RFRLEN1(wpf - 1); | ||
312 | regs->xcr1 |= XFRLEN1(wpf - 1); | ||
313 | break; | ||
314 | default: | ||
315 | /* Unsupported number of channels */ | ||
316 | return -EINVAL; | ||
317 | } | 319 | } |
318 | 320 | ||
321 | regs->rcr1 |= RFRLEN1(wpf - 1); | ||
322 | regs->xcr1 |= XFRLEN1(wpf - 1); | ||
323 | |||
319 | switch (params_format(params)) { | 324 | switch (params_format(params)) { |
320 | case SNDRV_PCM_FORMAT_S16_LE: | 325 | case SNDRV_PCM_FORMAT_S16_LE: |
321 | /* Set word lengths */ | 326 | /* Set word lengths */ |
@@ -330,15 +335,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
330 | return -EINVAL; | 335 | return -EINVAL; |
331 | } | 336 | } |
332 | 337 | ||
338 | /* In McBSP master modes, FRAME (i.e. sample rate) is generated | ||
339 | * by _counting_ BCLKs. Calculate frame size in BCLKs */ | ||
340 | master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; | ||
341 | if (master == SND_SOC_DAIFMT_CBS_CFS) { | ||
342 | div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; | ||
343 | framesize = (mcbsp_data->in_freq / div) / params_rate(params); | ||
344 | |||
345 | if (framesize < wlen * channels) { | ||
346 | printk(KERN_ERR "%s: not enough bandwidth for desired rate and " | ||
347 | "channels\n", __func__); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | } else | ||
351 | framesize = wlen * channels; | ||
352 | |||
333 | /* Set FS period and length in terms of bit clock periods */ | 353 | /* Set FS period and length in terms of bit clock periods */ |
334 | switch (format) { | 354 | switch (format) { |
335 | case SND_SOC_DAIFMT_I2S: | 355 | case SND_SOC_DAIFMT_I2S: |
336 | regs->srgr2 |= FPER(wlen * channels - 1); | 356 | regs->srgr2 |= FPER(framesize - 1); |
337 | regs->srgr1 |= FWID(wlen - 1); | 357 | regs->srgr1 |= FWID((framesize >> 1) - 1); |
338 | break; | 358 | break; |
339 | case SND_SOC_DAIFMT_DSP_A: | 359 | case SND_SOC_DAIFMT_DSP_A: |
340 | case SND_SOC_DAIFMT_DSP_B: | 360 | case SND_SOC_DAIFMT_DSP_B: |
341 | regs->srgr2 |= FPER(wlen * channels - 1); | 361 | regs->srgr2 |= FPER(framesize - 1); |
342 | regs->srgr1 |= FWID(0); | 362 | regs->srgr1 |= FWID(0); |
343 | break; | 363 | break; |
344 | } | 364 | } |
@@ -454,6 +474,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
454 | if (div_id != OMAP_MCBSP_CLKGDV) | 474 | if (div_id != OMAP_MCBSP_CLKGDV) |
455 | return -ENODEV; | 475 | return -ENODEV; |
456 | 476 | ||
477 | mcbsp_data->clk_div = div; | ||
457 | regs->srgr1 |= CLKGDV(div - 1); | 478 | regs->srgr1 |= CLKGDV(div - 1); |
458 | 479 | ||
459 | return 0; | 480 | return 0; |
@@ -554,6 +575,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
554 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 575 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
555 | int err = 0; | 576 | int err = 0; |
556 | 577 | ||
578 | mcbsp_data->in_freq = freq; | ||
579 | |||
557 | switch (clk_id) { | 580 | switch (clk_id) { |
558 | case OMAP_MCBSP_SYSCLK_CLK: | 581 | case OMAP_MCBSP_SYSCLK_CLK: |
559 | regs->srgr2 |= CLKSM; | 582 | regs->srgr2 |= CLKSM; |
@@ -598,13 +621,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { | |||
598 | .id = (link_id), \ | 621 | .id = (link_id), \ |
599 | .playback = { \ | 622 | .playback = { \ |
600 | .channels_min = 1, \ | 623 | .channels_min = 1, \ |
601 | .channels_max = 4, \ | 624 | .channels_max = 16, \ |
602 | .rates = OMAP_MCBSP_RATES, \ | 625 | .rates = OMAP_MCBSP_RATES, \ |
603 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 626 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
604 | }, \ | 627 | }, \ |
605 | .capture = { \ | 628 | .capture = { \ |
606 | .channels_min = 1, \ | 629 | .channels_min = 1, \ |
607 | .channels_max = 4, \ | 630 | .channels_max = 16, \ |
608 | .rates = OMAP_MCBSP_RATES, \ | 631 | .rates = OMAP_MCBSP_RATES, \ |
609 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 632 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
610 | }, \ | 633 | }, \ |
@@ -626,6 +649,136 @@ struct snd_soc_dai omap_mcbsp_dai[] = { | |||
626 | 649 | ||
627 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); | 650 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); |
628 | 651 | ||
652 | int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | ||
653 | struct snd_ctl_elem_info *uinfo) | ||
654 | { | ||
655 | struct soc_mixer_control *mc = | ||
656 | (struct soc_mixer_control *)kcontrol->private_value; | ||
657 | int max = mc->max; | ||
658 | int min = mc->min; | ||
659 | |||
660 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
661 | uinfo->count = 1; | ||
662 | uinfo->value.integer.min = min; | ||
663 | uinfo->value.integer.max = max; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ | ||
668 | static int \ | ||
669 | omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
670 | struct snd_ctl_elem_value *uc) \ | ||
671 | { \ | ||
672 | struct soc_mixer_control *mc = \ | ||
673 | (struct soc_mixer_control *)kc->private_value; \ | ||
674 | int max = mc->max; \ | ||
675 | int min = mc->min; \ | ||
676 | int val = uc->value.integer.value[0]; \ | ||
677 | \ | ||
678 | if (val < min || val > max) \ | ||
679 | return -EINVAL; \ | ||
680 | \ | ||
681 | /* OMAP McBSP implementation uses index values 0..4 */ \ | ||
682 | return omap_st_set_chgain((id)-1, channel, val); \ | ||
683 | } | ||
684 | |||
685 | #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ | ||
686 | static int \ | ||
687 | omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | ||
688 | struct snd_ctl_elem_value *uc) \ | ||
689 | { \ | ||
690 | s16 chgain; \ | ||
691 | \ | ||
692 | if (omap_st_get_chgain((id)-1, channel, &chgain)) \ | ||
693 | return -EAGAIN; \ | ||
694 | \ | ||
695 | uc->value.integer.value[0] = chgain; \ | ||
696 | return 0; \ | ||
697 | } | ||
698 | |||
699 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) | ||
700 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) | ||
701 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) | ||
702 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) | ||
703 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) | ||
704 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) | ||
705 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) | ||
706 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) | ||
707 | |||
708 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, | ||
709 | struct snd_ctl_elem_value *ucontrol) | ||
710 | { | ||
711 | struct soc_mixer_control *mc = | ||
712 | (struct soc_mixer_control *)kcontrol->private_value; | ||
713 | u8 value = ucontrol->value.integer.value[0]; | ||
714 | |||
715 | if (value == omap_st_is_enabled(mc->reg)) | ||
716 | return 0; | ||
717 | |||
718 | if (value) | ||
719 | omap_st_enable(mc->reg); | ||
720 | else | ||
721 | omap_st_disable(mc->reg); | ||
722 | |||
723 | return 1; | ||
724 | } | ||
725 | |||
726 | static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, | ||
727 | struct snd_ctl_elem_value *ucontrol) | ||
728 | { | ||
729 | struct soc_mixer_control *mc = | ||
730 | (struct soc_mixer_control *)kcontrol->private_value; | ||
731 | |||
732 | ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { | ||
737 | SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, | ||
738 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
739 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", | ||
740 | -32768, 32767, | ||
741 | omap_mcbsp2_get_st_ch0_volume, | ||
742 | omap_mcbsp2_set_st_ch0_volume), | ||
743 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", | ||
744 | -32768, 32767, | ||
745 | omap_mcbsp2_get_st_ch1_volume, | ||
746 | omap_mcbsp2_set_st_ch1_volume), | ||
747 | }; | ||
748 | |||
749 | static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { | ||
750 | SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, | ||
751 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
752 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", | ||
753 | -32768, 32767, | ||
754 | omap_mcbsp3_get_st_ch0_volume, | ||
755 | omap_mcbsp3_set_st_ch0_volume), | ||
756 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", | ||
757 | -32768, 32767, | ||
758 | omap_mcbsp3_get_st_ch1_volume, | ||
759 | omap_mcbsp3_set_st_ch1_volume), | ||
760 | }; | ||
761 | |||
762 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) | ||
763 | { | ||
764 | if (!cpu_is_omap34xx()) | ||
765 | return -ENODEV; | ||
766 | |||
767 | switch (mcbsp_id) { | ||
768 | case 1: /* McBSP 2 */ | ||
769 | return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, | ||
770 | ARRAY_SIZE(omap_mcbsp2_st_controls)); | ||
771 | case 2: /* McBSP 3 */ | ||
772 | return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, | ||
773 | ARRAY_SIZE(omap_mcbsp3_st_controls)); | ||
774 | default: | ||
775 | break; | ||
776 | } | ||
777 | |||
778 | return -EINVAL; | ||
779 | } | ||
780 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | ||
781 | |||
629 | static int __init snd_omap_mcbsp_init(void) | 782 | static int __init snd_omap_mcbsp_init(void) |
630 | { | 783 | { |
631 | return snd_soc_register_dais(omap_mcbsp_dai, | 784 | return snd_soc_register_dais(omap_mcbsp_dai, |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 647d2f981ab0..6c363e5f4387 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -50,11 +50,13 @@ enum omap_mcbsp_div { | |||
50 | #undef NUM_LINKS | 50 | #undef NUM_LINKS |
51 | #define NUM_LINKS 3 | 51 | #define NUM_LINKS 3 |
52 | #endif | 52 | #endif |
53 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | 53 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
54 | #undef NUM_LINKS | 54 | #undef NUM_LINKS |
55 | #define NUM_LINKS 5 | 55 | #define NUM_LINKS 5 |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; | 58 | extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; |
59 | 59 | ||
60 | int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); | ||
61 | |||
60 | #endif | 62 | #endif |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c new file mode 100644 index 000000000000..b7f4f7e015f3 --- /dev/null +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments | ||
5 | * | ||
6 | * Author: Misael Lopez Cruz <x0052729@ti.com> | ||
7 | * Contact: Jorge Eduardo Candelaria <x0107209@ti.com> | ||
8 | * Margarita Olaya <magi.olaya@ti.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; 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 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <sound/core.h> | ||
30 | #include <sound/pcm.h> | ||
31 | #include <sound/pcm_params.h> | ||
32 | #include <sound/initval.h> | ||
33 | #include <sound/soc.h> | ||
34 | |||
35 | #include <plat/control.h> | ||
36 | #include <plat/dma.h> | ||
37 | #include <plat/mcbsp.h> | ||
38 | #include "mcpdm.h" | ||
39 | #include "omap-mcpdm.h" | ||
40 | #include "omap-pcm.h" | ||
41 | |||
42 | struct omap_mcpdm_data { | ||
43 | struct omap_mcpdm_link *links; | ||
44 | int active; | ||
45 | }; | ||
46 | |||
47 | static struct omap_mcpdm_link omap_mcpdm_links[] = { | ||
48 | /* downlink */ | ||
49 | { | ||
50 | .irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL, | ||
51 | .threshold = 1, | ||
52 | .format = PDMOUTFORMAT_LJUST, | ||
53 | }, | ||
54 | /* uplink */ | ||
55 | { | ||
56 | .irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL, | ||
57 | .threshold = 1, | ||
58 | .format = PDMOUTFORMAT_LJUST, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static struct omap_mcpdm_data mcpdm_data = { | ||
63 | .links = omap_mcpdm_links, | ||
64 | .active = 0, | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Stream DMA parameters | ||
69 | */ | ||
70 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { | ||
71 | { | ||
72 | .name = "Audio playback", | ||
73 | .dma_req = OMAP44XX_DMA_MCPDM_DL, | ||
74 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
75 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
76 | .packet_size = 16, | ||
77 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA, | ||
78 | }, | ||
79 | { | ||
80 | .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 | .packet_size = 16, | ||
85 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA, | ||
86 | }, | ||
87 | }; | ||
88 | |||
89 | static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | ||
90 | struct snd_soc_dai *dai) | ||
91 | { | ||
92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
93 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
94 | int err = 0; | ||
95 | |||
96 | if (!cpu_dai->active) | ||
97 | err = omap_mcpdm_request(); | ||
98 | |||
99 | return err; | ||
100 | } | ||
101 | |||
102 | static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, | ||
103 | struct snd_soc_dai *dai) | ||
104 | { | ||
105 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
106 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
107 | |||
108 | if (!cpu_dai->active) | ||
109 | omap_mcpdm_free(); | ||
110 | } | ||
111 | |||
112 | static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, | ||
113 | struct snd_soc_dai *dai) | ||
114 | { | ||
115 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
116 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
117 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
118 | int stream = substream->stream; | ||
119 | int err = 0; | ||
120 | |||
121 | switch (cmd) { | ||
122 | case SNDRV_PCM_TRIGGER_START: | ||
123 | case SNDRV_PCM_TRIGGER_RESUME: | ||
124 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
125 | if (!mcpdm_priv->active++) | ||
126 | omap_mcpdm_start(stream); | ||
127 | break; | ||
128 | |||
129 | case SNDRV_PCM_TRIGGER_STOP: | ||
130 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
131 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
132 | if (!--mcpdm_priv->active) | ||
133 | omap_mcpdm_stop(stream); | ||
134 | break; | ||
135 | default: | ||
136 | err = -EINVAL; | ||
137 | } | ||
138 | |||
139 | return err; | ||
140 | } | ||
141 | |||
142 | static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | ||
143 | struct snd_pcm_hw_params *params, | ||
144 | struct snd_soc_dai *dai) | ||
145 | { | ||
146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
147 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
148 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
149 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; | ||
150 | int stream = substream->stream; | ||
151 | int channels, err, link_mask = 0; | ||
152 | |||
153 | snd_soc_dai_set_dma_data(cpu_dai, substream, | ||
154 | &omap_mcpdm_dai_dma_params[stream]); | ||
155 | |||
156 | channels = params_channels(params); | ||
157 | switch (channels) { | ||
158 | case 4: | ||
159 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | ||
160 | /* up to 2 channels for capture */ | ||
161 | return -EINVAL; | ||
162 | link_mask |= 1 << 3; | ||
163 | case 3: | ||
164 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | ||
165 | /* up to 2 channels for capture */ | ||
166 | return -EINVAL; | ||
167 | link_mask |= 1 << 2; | ||
168 | case 2: | ||
169 | link_mask |= 1 << 1; | ||
170 | case 1: | ||
171 | link_mask |= 1 << 0; | ||
172 | break; | ||
173 | default: | ||
174 | /* unsupported number of channels */ | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
179 | mcpdm_links[stream].channels = link_mask << 3; | ||
180 | err = omap_mcpdm_playback_open(&mcpdm_links[stream]); | ||
181 | } else { | ||
182 | mcpdm_links[stream].channels = link_mask << 0; | ||
183 | err = omap_mcpdm_capture_open(&mcpdm_links[stream]); | ||
184 | } | ||
185 | |||
186 | return err; | ||
187 | } | ||
188 | |||
189 | static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, | ||
190 | struct snd_soc_dai *dai) | ||
191 | { | ||
192 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
193 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
194 | struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; | ||
195 | struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; | ||
196 | int stream = substream->stream; | ||
197 | int err; | ||
198 | |||
199 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
200 | err = omap_mcpdm_playback_close(&mcpdm_links[stream]); | ||
201 | else | ||
202 | err = omap_mcpdm_capture_close(&mcpdm_links[stream]); | ||
203 | |||
204 | return err; | ||
205 | } | ||
206 | |||
207 | static struct snd_soc_dai_ops omap_mcpdm_dai_ops = { | ||
208 | .startup = omap_mcpdm_dai_startup, | ||
209 | .shutdown = omap_mcpdm_dai_shutdown, | ||
210 | .trigger = omap_mcpdm_dai_trigger, | ||
211 | .hw_params = omap_mcpdm_dai_hw_params, | ||
212 | .hw_free = omap_mcpdm_dai_hw_free, | ||
213 | }; | ||
214 | |||
215 | #define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
216 | #define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) | ||
217 | |||
218 | struct snd_soc_dai omap_mcpdm_dai = { | ||
219 | .name = "omap-mcpdm", | ||
220 | .id = -1, | ||
221 | .playback = { | ||
222 | .channels_min = 1, | ||
223 | .channels_max = 4, | ||
224 | .rates = OMAP_MCPDM_RATES, | ||
225 | .formats = OMAP_MCPDM_FORMATS, | ||
226 | }, | ||
227 | .capture = { | ||
228 | .channels_min = 1, | ||
229 | .channels_max = 2, | ||
230 | .rates = OMAP_MCPDM_RATES, | ||
231 | .formats = OMAP_MCPDM_FORMATS, | ||
232 | }, | ||
233 | .ops = &omap_mcpdm_dai_ops, | ||
234 | .private_data = &mcpdm_data, | ||
235 | }; | ||
236 | EXPORT_SYMBOL_GPL(omap_mcpdm_dai); | ||
237 | |||
238 | static int __init snd_omap_mcpdm_init(void) | ||
239 | { | ||
240 | return snd_soc_register_dai(&omap_mcpdm_dai); | ||
241 | } | ||
242 | module_init(snd_omap_mcpdm_init); | ||
243 | |||
244 | static void __exit snd_omap_mcpdm_exit(void) | ||
245 | { | ||
246 | snd_soc_unregister_dai(&omap_mcpdm_dai); | ||
247 | } | ||
248 | module_exit(snd_omap_mcpdm_exit); | ||
249 | |||
250 | MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>"); | ||
251 | MODULE_DESCRIPTION("OMAP PDM SoC Interface"); | ||
252 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h new file mode 100644 index 000000000000..73b80d559345 --- /dev/null +++ b/sound/soc/omap/omap-mcpdm.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * omap-mcpdm.h | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments | ||
5 | * | ||
6 | * Contact: Misael Lopez Cruz <x0052729@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 | #ifndef __OMAP_MCPDM_H__ | ||
25 | #define __OMAP_MCPDM_H__ | ||
26 | |||
27 | extern struct snd_soc_dai omap_mcpdm_dai; | ||
28 | |||
29 | #endif /* End of __OMAP_MCPDM_H__ */ | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 6a829eef2a4f..1e521904ea64 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -23,12 +23,13 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/slab.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
28 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
29 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
30 | 31 | ||
31 | #include <mach/dma.h> | 32 | #include <plat/dma.h> |
32 | #include "omap-pcm.h" | 33 | #include "omap-pcm.h" |
33 | 34 | ||
34 | static const struct snd_pcm_hardware omap_pcm_hardware = { | 35 | static const struct snd_pcm_hardware omap_pcm_hardware = { |
@@ -37,7 +38,8 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
37 | SNDRV_PCM_INFO_INTERLEAVED | | 38 | SNDRV_PCM_INFO_INTERLEAVED | |
38 | SNDRV_PCM_INFO_PAUSE | | 39 | SNDRV_PCM_INFO_PAUSE | |
39 | SNDRV_PCM_INFO_RESUME, | 40 | SNDRV_PCM_INFO_RESUME, |
40 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 41 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
42 | SNDRV_PCM_FMTBIT_S32_LE, | ||
41 | .period_bytes_min = 32, | 43 | .period_bytes_min = 32, |
42 | .period_bytes_max = 64 * 1024, | 44 | .period_bytes_max = 64 * 1024, |
43 | .periods_min = 2, | 45 | .periods_min = 2, |
@@ -59,12 +61,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data) | |||
59 | struct omap_runtime_data *prtd = runtime->private_data; | 61 | struct omap_runtime_data *prtd = runtime->private_data; |
60 | unsigned long flags; | 62 | unsigned long flags; |
61 | 63 | ||
62 | if ((cpu_is_omap1510()) && | 64 | if ((cpu_is_omap1510())) { |
63 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { | ||
64 | /* | 65 | /* |
65 | * OMAP1510 doesn't fully support DMA progress counter | 66 | * OMAP1510 doesn't fully support DMA progress counter |
66 | * and there is no software emulation implemented yet, | 67 | * and there is no software emulation implemented yet, |
67 | * so have to maintain our own playback progress counter | 68 | * so have to maintain our own progress counters |
68 | * that can be used by omap_pcm_pointer() instead. | 69 | * that can be used by omap_pcm_pointer() instead. |
69 | */ | 70 | */ |
70 | spin_lock_irqsave(&prtd->lock, flags); | 71 | spin_lock_irqsave(&prtd->lock, flags); |
@@ -99,9 +100,11 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
99 | struct snd_pcm_runtime *runtime = substream->runtime; | 100 | struct snd_pcm_runtime *runtime = substream->runtime; |
100 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 101 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
101 | struct omap_runtime_data *prtd = runtime->private_data; | 102 | struct omap_runtime_data *prtd = runtime->private_data; |
102 | struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data; | 103 | struct omap_pcm_dma_data *dma_data; |
103 | int err = 0; | 104 | int err = 0; |
104 | 105 | ||
106 | dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | ||
107 | |||
105 | /* return if this is a bufferless transfer e.g. | 108 | /* return if this is a bufferless transfer e.g. |
106 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 109 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
107 | if (!dma_data) | 110 | if (!dma_data) |
@@ -149,6 +152,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
149 | struct omap_runtime_data *prtd = runtime->private_data; | 152 | struct omap_runtime_data *prtd = runtime->private_data; |
150 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; | 153 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; |
151 | struct omap_dma_channel_params dma_params; | 154 | struct omap_dma_channel_params dma_params; |
155 | int bytes; | ||
152 | 156 | ||
153 | /* return if this is a bufferless transfer e.g. | 157 | /* return if this is a bufferless transfer e.g. |
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | 158 | * codec <--> BT codec or GSM modem -- lg FIXME */ |
@@ -156,11 +160,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
156 | return 0; | 160 | return 0; |
157 | 161 | ||
158 | memset(&dma_params, 0, sizeof(dma_params)); | 162 | memset(&dma_params, 0, sizeof(dma_params)); |
159 | /* | 163 | dma_params.data_type = dma_data->data_type; |
160 | * Note: Regardless of interface data formats supported by OMAP McBSP | ||
161 | * or EAC blocks, internal representation is always fixed 16-bit/sample | ||
162 | */ | ||
163 | dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; | ||
164 | dma_params.trigger = dma_data->dma_req; | 164 | dma_params.trigger = dma_data->dma_req; |
165 | dma_params.sync_mode = dma_data->sync_mode; | 165 | dma_params.sync_mode = dma_data->sync_mode; |
166 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 166 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -170,6 +170,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
170 | dma_params.src_start = runtime->dma_addr; | 170 | dma_params.src_start = runtime->dma_addr; |
171 | dma_params.dst_start = dma_data->port_addr; | 171 | dma_params.dst_start = dma_data->port_addr; |
172 | dma_params.dst_port = OMAP_DMA_PORT_MPUI; | 172 | dma_params.dst_port = OMAP_DMA_PORT_MPUI; |
173 | dma_params.dst_fi = dma_data->packet_size; | ||
173 | } else { | 174 | } else { |
174 | dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; | 175 | dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; |
175 | dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; | 176 | dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; |
@@ -177,6 +178,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
177 | dma_params.src_start = dma_data->port_addr; | 178 | dma_params.src_start = dma_data->port_addr; |
178 | dma_params.dst_start = runtime->dma_addr; | 179 | dma_params.dst_start = runtime->dma_addr; |
179 | dma_params.src_port = OMAP_DMA_PORT_MPUI; | 180 | dma_params.src_port = OMAP_DMA_PORT_MPUI; |
181 | dma_params.src_fi = dma_data->packet_size; | ||
180 | } | 182 | } |
181 | /* | 183 | /* |
182 | * Set DMA transfer frame size equal to ALSA period size and frame | 184 | * Set DMA transfer frame size equal to ALSA period size and frame |
@@ -184,12 +186,12 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) | |||
184 | * we can transfer the whole ALSA buffer with single DMA transfer but | 186 | * we can transfer the whole ALSA buffer with single DMA transfer but |
185 | * still can get an interrupt at each period bounary | 187 | * still can get an interrupt at each period bounary |
186 | */ | 188 | */ |
187 | dma_params.elem_count = snd_pcm_lib_period_bytes(substream) / 2; | 189 | bytes = snd_pcm_lib_period_bytes(substream); |
190 | dma_params.elem_count = bytes >> dma_data->data_type; | ||
188 | dma_params.frame_count = runtime->periods; | 191 | dma_params.frame_count = runtime->periods; |
189 | omap_set_dma_params(prtd->dma_ch, &dma_params); | 192 | omap_set_dma_params(prtd->dma_ch, &dma_params); |
190 | 193 | ||
191 | if ((cpu_is_omap1510()) && | 194 | if ((cpu_is_omap1510())) |
192 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) | ||
193 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | | 195 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | |
194 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); | 196 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); |
195 | else | 197 | else |
@@ -247,14 +249,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | |||
247 | dma_addr_t ptr; | 249 | dma_addr_t ptr; |
248 | snd_pcm_uframes_t offset; | 250 | snd_pcm_uframes_t offset; |
249 | 251 | ||
250 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 252 | if (cpu_is_omap1510()) { |
253 | offset = prtd->period_index * runtime->period_size; | ||
254 | } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
251 | ptr = omap_get_dma_dst_pos(prtd->dma_ch); | 255 | ptr = omap_get_dma_dst_pos(prtd->dma_ch); |
252 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | 256 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); |
253 | } else if (!(cpu_is_omap1510())) { | 257 | } else { |
254 | ptr = omap_get_dma_src_pos(prtd->dma_ch); | 258 | ptr = omap_get_dma_src_pos(prtd->dma_ch); |
255 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | 259 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); |
256 | } else | 260 | } |
257 | offset = prtd->period_index * runtime->period_size; | ||
258 | 261 | ||
259 | if (offset >= runtime->buffer_size) | 262 | if (offset >= runtime->buffer_size) |
260 | offset = 0; | 263 | offset = 0; |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index 38a821dd4118..b19975d26907 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
@@ -29,8 +29,10 @@ struct omap_pcm_dma_data { | |||
29 | char *name; /* stream identifier */ | 29 | char *name; /* stream identifier */ |
30 | int dma_req; /* DMA request line */ | 30 | int dma_req; /* DMA request line */ |
31 | unsigned long port_addr; /* transmit/receive register */ | 31 | unsigned long port_addr; /* transmit/receive register */ |
32 | int sync_mode; /* DMA sync mode */ | ||
33 | void (*set_threshold)(struct snd_pcm_substream *substream); | 32 | void (*set_threshold)(struct snd_pcm_substream *substream); |
33 | int data_type; /* data type 8,16,32 */ | ||
34 | int sync_mode; /* DMA sync mode */ | ||
35 | int packet_size; /* packet size only in PACKET mode */ | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | extern struct snd_soc_platform omap_soc_platform; | 38 | extern struct snd_soc_platform omap_soc_platform; |
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c index 027e1a40f8a1..c7adea38274c 100644 --- a/sound/soc/omap/omap2evm.c +++ b/sound/soc/omap/omap2evm.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
32 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
33 | #include <mach/gpio.h> | 33 | #include <mach/gpio.h> |
34 | #include <mach/mcbsp.h> | 34 | #include <plat/mcbsp.h> |
35 | 35 | ||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c index b0cff9f33b7e..240e0975dd6a 100644 --- a/sound/soc/omap/omap3beagle.c +++ b/sound/soc/omap/omap3beagle.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/gpio.h> | 31 | #include <mach/gpio.h> |
32 | #include <mach/mcbsp.h> | 32 | #include <plat/mcbsp.h> |
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
@@ -117,11 +117,11 @@ static int __init omap3beagle_soc_init(void) | |||
117 | { | 117 | { |
118 | int ret; | 118 | int ret; |
119 | 119 | ||
120 | if (!machine_is_omap3_beagle()) { | 120 | if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) { |
121 | pr_debug("Not OMAP3 Beagle!\n"); | 121 | pr_debug("Not OMAP3 Beagle or Devkit8000!\n"); |
122 | return -ENODEV; | 122 | return -ENODEV; |
123 | } | 123 | } |
124 | pr_info("OMAP3 Beagle SoC init\n"); | 124 | pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); |
125 | 125 | ||
126 | omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); | 126 | omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); |
127 | if (!omap3beagle_snd_device) { | 127 | if (!omap3beagle_snd_device) { |
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c index 13aa380de162..dfcb344092e4 100644 --- a/sound/soc/omap/omap3evm.c +++ b/sound/soc/omap/omap3evm.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
28 | #include <mach/hardware.h> | 28 | #include <mach/hardware.h> |
29 | #include <mach/gpio.h> | 29 | #include <mach/gpio.h> |
30 | #include <mach/mcbsp.h> | 30 | #include <plat/mcbsp.h> |
31 | 31 | ||
32 | #include "omap-mcbsp.h" | 32 | #include "omap-mcbsp.h" |
33 | #include "omap-pcm.h" | 33 | #include "omap-pcm.h" |
@@ -93,10 +93,17 @@ static struct snd_soc_card snd_soc_omap3evm = { | |||
93 | .num_links = 1, | 93 | .num_links = 1, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /* twl4030 setup */ | ||
97 | static struct twl4030_setup_data twl4030_setup = { | ||
98 | .ramp_delay_value = 4, | ||
99 | .sysclk = 26000, | ||
100 | }; | ||
101 | |||
96 | /* Audio subsystem */ | 102 | /* Audio subsystem */ |
97 | static struct snd_soc_device omap3evm_snd_devdata = { | 103 | static struct snd_soc_device omap3evm_snd_devdata = { |
98 | .card = &snd_soc_omap3evm, | 104 | .card = &snd_soc_omap3evm, |
99 | .codec_dev = &soc_codec_dev_twl4030, | 105 | .codec_dev = &soc_codec_dev_twl4030, |
106 | .codec_data = &twl4030_setup, | ||
100 | }; | 107 | }; |
101 | 108 | ||
102 | static struct platform_device *omap3evm_snd_device; | 109 | static struct platform_device *omap3evm_snd_device; |
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 0cd06f5dd356..de10f76baded 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/regulator/consumer.h> | ||
26 | 27 | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
@@ -40,9 +41,14 @@ | |||
40 | 41 | ||
41 | #define PREFIX "ASoC omap3pandora: " | 42 | #define PREFIX "ASoC omap3pandora: " |
42 | 43 | ||
43 | static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, | 44 | static struct regulator *omap3pandora_dac_reg; |
44 | struct snd_soc_dai *cpu_dai, unsigned int fmt) | 45 | |
46 | static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream, | ||
47 | struct snd_pcm_hw_params *params, unsigned int fmt) | ||
45 | { | 48 | { |
49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
50 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
51 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
46 | int ret; | 52 | int ret; |
47 | 53 | ||
48 | /* Set codec DAI configuration */ | 54 | /* Set codec DAI configuration */ |
@@ -68,8 +74,9 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, | |||
68 | } | 74 | } |
69 | 75 | ||
70 | /* Set McBSP clock to external */ | 76 | /* Set McBSP clock to external */ |
71 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0, | 77 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, |
72 | SND_SOC_CLOCK_IN); | 78 | 256 * params_rate(params), |
79 | SND_SOC_CLOCK_IN); | ||
73 | if (ret < 0) { | 80 | if (ret < 0) { |
74 | pr_err(PREFIX "can't set cpu system clock\n"); | 81 | pr_err(PREFIX "can't set cpu system clock\n"); |
75 | return ret; | 82 | return ret; |
@@ -87,11 +94,7 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, | |||
87 | static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, | 94 | static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, |
88 | struct snd_pcm_hw_params *params) | 95 | struct snd_pcm_hw_params *params) |
89 | { | 96 | { |
90 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 97 | return omap3pandora_cmn_hw_params(substream, params, |
91 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
92 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
93 | |||
94 | return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, | ||
95 | SND_SOC_DAIFMT_I2S | | 98 | SND_SOC_DAIFMT_I2S | |
96 | SND_SOC_DAIFMT_IB_NF | | 99 | SND_SOC_DAIFMT_IB_NF | |
97 | SND_SOC_DAIFMT_CBS_CFS); | 100 | SND_SOC_DAIFMT_CBS_CFS); |
@@ -100,31 +103,43 @@ static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, | |||
100 | static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream, | 103 | static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream, |
101 | struct snd_pcm_hw_params *params) | 104 | struct snd_pcm_hw_params *params) |
102 | { | 105 | { |
103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 106 | return omap3pandora_cmn_hw_params(substream, params, |
104 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
105 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
106 | |||
107 | return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, | ||
108 | SND_SOC_DAIFMT_I2S | | 107 | SND_SOC_DAIFMT_I2S | |
109 | SND_SOC_DAIFMT_NB_NF | | 108 | SND_SOC_DAIFMT_NB_NF | |
110 | SND_SOC_DAIFMT_CBS_CFS); | 109 | SND_SOC_DAIFMT_CBS_CFS); |
111 | } | 110 | } |
112 | 111 | ||
113 | static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, | 112 | static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, |
114 | struct snd_kcontrol *k, int event) | 113 | struct snd_kcontrol *k, int event) |
115 | { | 114 | { |
115 | /* | ||
116 | * The PCM1773 DAC datasheet requires 1ms delay between switching | ||
117 | * VCC power on/off and /PD pin high/low | ||
118 | */ | ||
116 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 119 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
120 | regulator_enable(omap3pandora_dac_reg); | ||
121 | mdelay(1); | ||
117 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); | 122 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); |
118 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1); | ||
119 | } else { | 123 | } else { |
120 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0); | ||
121 | mdelay(1); | ||
122 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0); | 124 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0); |
125 | mdelay(1); | ||
126 | regulator_disable(omap3pandora_dac_reg); | ||
123 | } | 127 | } |
124 | 128 | ||
125 | return 0; | 129 | return 0; |
126 | } | 130 | } |
127 | 131 | ||
132 | static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, | ||
133 | struct snd_kcontrol *k, int event) | ||
134 | { | ||
135 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
136 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1); | ||
137 | else | ||
138 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
128 | /* | 143 | /* |
129 | * Audio paths on Pandora board: | 144 | * Audio paths on Pandora board: |
130 | * | 145 | * |
@@ -134,7 +149,9 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, | |||
134 | * |P| <--- TWL4030 <--------- Line In and MICs | 149 | * |P| <--- TWL4030 <--------- Line In and MICs |
135 | */ | 150 | */ |
136 | static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { | 151 | static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { |
137 | SND_SOC_DAPM_DAC("PCM DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0), | 152 | SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM, |
153 | 0, 0, omap3pandora_dac_event, | ||
154 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
138 | SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, | 155 | SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, |
139 | 0, 0, NULL, 0, omap3pandora_hp_event, | 156 | 0, 0, NULL, 0, omap3pandora_hp_event, |
140 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 157 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -149,6 +166,7 @@ static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { | |||
149 | }; | 166 | }; |
150 | 167 | ||
151 | static const struct snd_soc_dapm_route omap3pandora_out_map[] = { | 168 | static const struct snd_soc_dapm_route omap3pandora_out_map[] = { |
169 | {"PCM DAC", NULL, "APLL Enable"}, | ||
152 | {"Headphone Amplifier", NULL, "PCM DAC"}, | 170 | {"Headphone Amplifier", NULL, "PCM DAC"}, |
153 | {"Line Out", NULL, "PCM DAC"}, | 171 | {"Line Out", NULL, "PCM DAC"}, |
154 | {"Headphone Jack", NULL, "Headphone Amplifier"}, | 172 | {"Headphone Jack", NULL, "Headphone Amplifier"}, |
@@ -309,8 +327,18 @@ static int __init omap3pandora_soc_init(void) | |||
309 | goto fail2; | 327 | goto fail2; |
310 | } | 328 | } |
311 | 329 | ||
330 | omap3pandora_dac_reg = regulator_get(&omap3pandora_snd_device->dev, "vcc"); | ||
331 | if (IS_ERR(omap3pandora_dac_reg)) { | ||
332 | pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n", | ||
333 | dev_name(&omap3pandora_snd_device->dev), | ||
334 | PTR_ERR(omap3pandora_dac_reg)); | ||
335 | goto fail3; | ||
336 | } | ||
337 | |||
312 | return 0; | 338 | return 0; |
313 | 339 | ||
340 | fail3: | ||
341 | platform_device_del(omap3pandora_snd_device); | ||
314 | fail2: | 342 | fail2: |
315 | platform_device_put(omap3pandora_snd_device); | 343 | platform_device_put(omap3pandora_snd_device); |
316 | fail1: | 344 | fail1: |
@@ -323,6 +351,7 @@ module_init(omap3pandora_soc_init); | |||
323 | 351 | ||
324 | static void __exit omap3pandora_soc_exit(void) | 352 | static void __exit omap3pandora_soc_exit(void) |
325 | { | 353 | { |
354 | regulator_put(omap3pandora_dac_reg); | ||
326 | platform_device_unregister(omap3pandora_snd_device); | 355 | platform_device_unregister(omap3pandora_snd_device); |
327 | gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); | 356 | gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); |
328 | gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); | 357 | gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); |
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index a4e149b7f0eb..498ca2e03519 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
32 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
34 | #include <mach/mcbsp.h> | 34 | #include <plat/mcbsp.h> |
35 | 35 | ||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c index ec4f8fd8b3a2..c25f5276ad6f 100644 --- a/sound/soc/omap/overo.c +++ b/sound/soc/omap/overo.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/gpio.h> | 31 | #include <mach/gpio.h> |
32 | #include <mach/mcbsp.h> | 32 | #include <plat/mcbsp.h> |
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
@@ -107,8 +107,8 @@ static int __init overo_soc_init(void) | |||
107 | { | 107 | { |
108 | int ret; | 108 | int ret; |
109 | 109 | ||
110 | if (!machine_is_overo()) { | 110 | if (!(machine_is_overo() || machine_is_cm_t35())) { |
111 | pr_debug("Not Overo!\n"); | 111 | pr_debug("Incomatible machine!\n"); |
112 | return -ENODEV; | 112 | return -ENODEV; |
113 | } | 113 | } |
114 | printk(KERN_INFO "overo SoC init\n"); | 114 | printk(KERN_INFO "overo SoC init\n"); |
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 4a3f62d1f295..3c85c0f92823 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/i2c/twl4030.h> | 27 | #include <linux/i2c/twl.h> |
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
30 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
@@ -34,7 +34,7 @@ | |||
34 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
35 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
36 | #include <mach/gpio.h> | 36 | #include <mach/gpio.h> |
37 | #include <mach/mcbsp.h> | 37 | #include <plat/mcbsp.h> |
38 | 38 | ||
39 | #include "omap-mcbsp.h" | 39 | #include "omap-mcbsp.h" |
40 | #include "omap-pcm.h" | 40 | #include "omap-pcm.h" |
@@ -321,11 +321,11 @@ static int __init sdp3430_soc_init(void) | |||
321 | *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ | 321 | *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ |
322 | 322 | ||
323 | /* Set TWL4030 GPIO6 as EXTMUTE signal */ | 323 | /* Set TWL4030 GPIO6 as EXTMUTE signal */ |
324 | twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, | 324 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, |
325 | TWL4030_INTBR_PMBR1); | 325 | TWL4030_INTBR_PMBR1); |
326 | pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); | 326 | pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); |
327 | pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); | 327 | pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); |
328 | twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, | 328 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, |
329 | TWL4030_INTBR_PMBR1); | 329 | TWL4030_INTBR_PMBR1); |
330 | 330 | ||
331 | ret = platform_device_add(sdp3430_snd_device); | 331 | ret = platform_device_add(sdp3430_snd_device); |
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index f90b45f56220..f90a2ac888cf 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/gpio.h> | 31 | #include <mach/gpio.h> |
32 | #include <mach/mcbsp.h> | 32 | #include <plat/mcbsp.h> |
33 | 33 | ||
34 | #include "omap-mcbsp.h" | 34 | #include "omap-mcbsp.h" |
35 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |