aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/Kconfig200
-rw-r--r--sound/soc/tegra/Makefile34
-rw-r--r--sound/soc/tegra/tegra20_das.c333
-rw-r--r--sound/soc/tegra/tegra20_das.h148
-rw-r--r--sound/soc/tegra/tegra20_i2s.c586
-rw-r--r--sound/soc/tegra/tegra20_i2s.h198
-rw-r--r--sound/soc/tegra/tegra20_spdif.c463
-rw-r--r--sound/soc/tegra/tegra20_spdif.h556
-rw-r--r--sound/soc/tegra/tegra30_ahub.c665
-rw-r--r--sound/soc/tegra/tegra30_ahub.h512
-rw-r--r--sound/soc/tegra/tegra30_dam.c650
-rw-r--r--sound/soc/tegra/tegra30_dam.h163
-rw-r--r--sound/soc/tegra/tegra30_i2s.c949
-rw-r--r--sound/soc/tegra/tegra30_i2s.h274
-rw-r--r--sound/soc/tegra/tegra30_spdif.c505
-rw-r--r--sound/soc/tegra/tegra30_spdif.h777
-rw-r--r--sound/soc/tegra/tegra_aic326x.c1281
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c181
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h11
-rw-r--r--sound/soc/tegra/tegra_das.c265
-rw-r--r--sound/soc/tegra/tegra_das.h135
-rw-r--r--sound/soc/tegra/tegra_i2s.c509
-rw-r--r--sound/soc/tegra/tegra_i2s.h165
-rw-r--r--sound/soc/tegra/tegra_max98088.c1233
-rw-r--r--sound/soc/tegra/tegra_max98095.c723
-rw-r--r--sound/soc/tegra/tegra_p1852.c272
-rw-r--r--sound/soc/tegra/tegra_pcm.c74
-rw-r--r--sound/soc/tegra/tegra_rt5640.c738
-rw-r--r--sound/soc/tegra/tegra_wm8753.c972
-rw-r--r--sound/soc/tegra/tegra_wm8903.c592
30 files changed, 12986 insertions, 1178 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 035d39a4beb..2a8b4f1cef6 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -4,14 +4,55 @@ config SND_SOC_TEGRA
4 help 4 help
5 Say Y or M here if you want support for SoC audio on Tegra. 5 Say Y or M here if you want support for SoC audio on Tegra.
6 6
7config SND_SOC_TEGRA_I2S 7config SND_SOC_TEGRA20_DAS
8 tristate 8 tristate "Tegra 20 Digital Audio Switch driver"
9 depends on SND_SOC_TEGRA 9 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
10
11config SND_SOC_TEGRA20_I2S
12 tristate "Tegra 20 I2S driver"
13 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
14 select SND_SOC_TEGRA20_DAS
15 help
16 Say Y or M if you want to add support for codecs attached to the
17 Tegra I2S interface. You will also need to select the individual
18 machine drivers to support below.
19
20config SND_SOC_TEGRA30_AHUB
21 tristate "Tegra 30 Audio Hub driver"
22 depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
23
24config SND_SOC_TEGRA30_DAM
25 tristate "Tegra 30 Audio Dam driver"
26 depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
27 select SND_SOC_TEGRA30_AHUB
28
29config SND_SOC_TEGRA30_I2S
30 tristate "Tegra 30 I2S driver"
31 depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC
32 select SND_SOC_TEGRA30_AHUB
10 help 33 help
11 Say Y or M if you want to add support for codecs attached to the 34 Say Y or M if you want to add support for codecs attached to the
12 Tegra I2S interface. You will also need to select the individual 35 Tegra I2S interface. You will also need to select the individual
13 machine drivers to support below. 36 machine drivers to support below.
14 37
38config SND_SOC_TEGRA20_SPDIF
39 tristate
40 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC && TEGRA_DC
41 default m
42 help
43 Say Y or M if you want to add support for the TEGRA20 SPDIF interface.
44 You will also need to select the individual machine drivers to support
45 below.
46
47config SND_SOC_TEGRA30_SPDIF
48 tristate
49 depends on SND_SOC_TEGRA && ARCH_TEGRA_3x_SOC && TEGRA_DC
50 select SND_SOC_TEGRA30_AHUB
51 help
52 Say Y or M if you want to add support for the TEGRA30 SPDIF interface.
53 You will also need to select the individual machine drivers to support
54 below.
55
15config MACH_HAS_SND_SOC_TEGRA_WM8903 56config MACH_HAS_SND_SOC_TEGRA_WM8903
16 bool 57 bool
17 help 58 help
@@ -21,10 +62,15 @@ config MACH_HAS_SND_SOC_TEGRA_WM8903
21 62
22config SND_SOC_TEGRA_WM8903 63config SND_SOC_TEGRA_WM8903
23 tristate "SoC Audio support for Tegra boards using a WM8903 codec" 64 tristate "SoC Audio support for Tegra boards using a WM8903 codec"
24 depends on SND_SOC_TEGRA && I2C 65 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
25 depends on MACH_HAS_SND_SOC_TEGRA_WM8903 66 depends on MACH_HAS_SND_SOC_TEGRA_WM8903
26 select SND_SOC_TEGRA_I2S 67 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
68 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
69 select SND_SOC_TEGRA20_SPDIF if ARCH_TEGRA_2x_SOC
70 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
27 select SND_SOC_WM8903 71 select SND_SOC_WM8903
72 select SND_SOC_SPDIF
73 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
28 help 74 help
29 Say Y or M here if you want to add support for SoC audio on Tegra 75 Say Y or M here if you want to add support for SoC audio on Tegra
30 boards using the WM8093 codec. Currently, the supported boards are 76 boards using the WM8093 codec. Currently, the supported boards are
@@ -38,3 +84,147 @@ config SND_SOC_TEGRA_TRIMSLICE
38 help 84 help
39 Say Y or M here if you want to add support for SoC audio on the 85 Say Y or M here if you want to add support for SoC audio on the
40 TrimSlice platform. 86 TrimSlice platform.
87
88config SND_SOC_TEGRA_P1852
89 tristate "SoC Audio support for P1852 SKUs"
90 depends on SND_SOC_TEGRA
91 depends on MACH_P1852
92 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
93 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
94 select SND_SOC_SPDIF
95 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
96 help
97 Say Y or M here if you want to add support for SoC audio on the
98 TEGRA P1852 SKUs. These are plug-n-play boards and and the codecs
99 used by the system integrator needs to be provided while instantiating
100 the driver.
101
102config MACH_HAS_SND_SOC_TEGRA_WM8753
103 bool
104 help
105 Machines that use the SND_SOC_TEGRA_WM8753 driver should select
106 this config option, in order to allow the user to enable
107 SND_SOC_TEGRA_WM8753.
108
109config SND_SOC_TEGRA_WM8753
110 tristate "SoC Audio support for Tegra boards using a WM8753 codec"
111 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
112 depends on MACH_HAS_SND_SOC_TEGRA_WM8753
113 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
114 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
115 select SND_SOC_TEGRA20_SPDIF if ARCH_TEGRA_2x_SOC
116 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
117 select SND_SOC_WM8753
118 select SND_SOC_SPDIF
119 help
120 Say Y or M here if you want to add support for SoC audio on Tegra
121 boards using the WM8753 codec. Currently, only supported board is
122 Whistler.
123
124config MACH_HAS_SND_SOC_TEGRA_MAX98088
125 bool
126 help
127 Machines that use the SND_SOC_TEGRA_MAX98088 driver should select
128 this config option, in order to allow the user to enable
129 SND_SOC_TEGRA_MAX98088.
130
131config SND_SOC_TEGRA_MAX98088
132 tristate "SoC Audio support for Tegra boards using a MAX98088 codec"
133 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
134 depends on MACH_HAS_SND_SOC_TEGRA_MAX98088
135 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
136 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
137 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
138 select SND_SOC_MAX98088
139 select SND_SOC_SPDIF
140 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
141 help
142 Say Y or M here if you want to add support for SoC audio on Tegra
143 boards using the MAX98088 codec. Currently, only supported board is
144 Enterprise.
145
146config MACH_HAS_SND_SOC_TEGRA_TLV320AIC326X
147 bool
148 help
149 Machines that use the SND_SOC_TEGRA_TLV320AIC326X driver should select
150 this config option, in order to allow the user to enable
151 SND_SOC_TEGRA_TLV320AIC326X.
152
153config SND_SOC_TEGRA_TLV320AIC326X
154 tristate "SoC Audio support for Tegra boards using a TI AIC326x codec"
155 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
156 depends on MACH_HAS_SND_SOC_TEGRA_TLV320AIC326X
157 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
158 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
159 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
160 select SND_SOC_TLV320AIC326X
161 select SND_SOC_SPDIF
162 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
163 help
164 Say Y or M here if you want to add support for SoC audio on Tegra
165 boards using the TI AIC326X codec.
166
167config MACH_HAS_SND_SOC_TEGRA_RT5639
168 bool
169 help
170 Machines that use the SND_SOC_TEGRA_RT5639 driver should select
171 this config option, in order to allow the user to enable
172 SND_SOC_TEGRA_RT5639.
173
174config SND_SOC_TEGRA_RT5639
175 tristate "SoC Audio support for Tegra boards using a ALC5639 codec"
176 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
177 depends on MACH_HAS_SND_SOC_TEGRA_RT5639
178 depends on SND_SOC_TEGRA_RT5640
179 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
180 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
181 select SND_SOC_RT5639
182 select SND_SOC_SPDIF
183 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
184 help
185 Say Y or M here if you want to add support for SoC audio on Tegra
186 boards using the ALC5639 codec. Currently, the supported board
187 is Kai.
188
189config MACH_HAS_SND_SOC_TEGRA_RT5640
190 bool
191 help
192 Machines that use the SND_SOC_TEGRA_RT5640 driver should select
193 this config option, in order to allow the user to enable
194 SND_SOC_TEGRA_RT5640.
195
196config SND_SOC_TEGRA_RT5640
197 tristate "SoC Audio support for Tegra boards using a ALC5640 codec"
198 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
199 depends on MACH_HAS_SND_SOC_TEGRA_RT5640
200 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
201 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
202 select SND_SOC_RT5640
203 select SND_SOC_SPDIF
204 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
205 help
206 Say Y or M here if you want to add support for SoC audio on Tegra
207 boards using the ALC5640 codec. Currently, the supported boards
208 are Kai and Cardhu.
209
210config MACH_HAS_SND_SOC_TEGRA_MAX98095
211 bool
212 help
213 Machines that use the SND_SOC_TEGRA_MAX98095 driver should select
214 this config option, in order to allow the user to enable
215 SND_SOC_TEGRA_MAX98095.
216
217config SND_SOC_TEGRA_MAX98095
218 tristate "SoC Audio support for Tegra boards using a MAX98095 codec"
219 depends on SND_SOC_TEGRA && I2C && TEGRA_DC
220 depends on MACH_HAS_SND_SOC_TEGRA_MAX98095
221 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
222 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
223 select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
224 select SND_SOC_MAX98095
225 select SND_SOC_SPDIF
226 select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
227 help
228 Say Y or M here if you want to add support for SoC audio on Tegra
229 boards using the MAX98095 codec. Currently, only supported board is
230 Cardhu.
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index fa6574d92a3..d546046d1e1 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,17 +1,41 @@
1GCOV_PROFILE := y
2
1# Tegra platform Support 3# Tegra platform Support
2snd-soc-tegra-das-objs := tegra_das.o
3snd-soc-tegra-pcm-objs := tegra_pcm.o 4snd-soc-tegra-pcm-objs := tegra_pcm.o
4snd-soc-tegra-i2s-objs := tegra_i2s.o 5snd-soc-tegra20-spdif-objs := tegra20_spdif.o
5snd-soc-tegra-utils-objs += tegra_asoc_utils.o 6snd-soc-tegra-utils-objs += tegra_asoc_utils.o
7snd-soc-tegra20-das-objs := tegra20_das.o
8snd-soc-tegra20-i2s-objs := tegra20_i2s.o
9snd-soc-tegra30-ahub-objs := tegra30_ahub.o
10snd-soc-tegra30-i2s-objs := tegra30_i2s.o
11snd-soc-tegra30-spdif-objs := tegra30_spdif.o
12snd-soc-tegra30-dam-objs := tegra30_dam.o
6 13
7obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
8obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o
9obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o 14obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
10obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o 15obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
16obj-$(CONFIG_SND_SOC_TEGRA20_DAS) += snd-soc-tegra20-das.o
17obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o
18obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
19obj-$(CONFIG_SND_SOC_TEGRA30_DAM) += snd-soc-tegra30-dam.o
20obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
21obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o
22obj-$(CONFIG_SND_SOC_TEGRA30_SPDIF) += snd-soc-tegra30-spdif.o
11 23
12# Tegra machine Support 24# Tegra machine Support
13snd-soc-tegra-wm8903-objs := tegra_wm8903.o 25snd-soc-tegra-wm8903-objs := tegra_wm8903.o
14snd-soc-tegra-trimslice-objs := trimslice.o 26snd-soc-tegra-trimslice-objs := trimslice.o
27snd-soc-tegra-wm8753-objs := tegra_wm8753.o
28snd-soc-tegra-max98088-objs := tegra_max98088.o
29snd-soc-tegra-aic326x-objs := tegra_aic326x.o
30snd-soc-tegra-rt5640-objs := tegra_rt5640.o
31snd-soc-tegra-max98095-objs := tegra_max98095.o
32snd-soc-tegra-p1852-objs := tegra_p1852.o
15 33
16obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 34obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
17obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o 35obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
36obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
37obj-$(CONFIG_SND_SOC_TEGRA_MAX98088) += snd-soc-tegra-max98088.o
38obj-$(CONFIG_SND_SOC_TEGRA_TLV320AIC326X) += snd-soc-tegra-aic326x.o
39obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
40obj-$(CONFIG_SND_SOC_TEGRA_MAX98095) += snd-soc-tegra-max98095.o
41obj-$(CONFIG_SND_SOC_TEGRA_P1852) += snd-soc-tegra-p1852.o
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
new file mode 100644
index 00000000000..0774d360399
--- /dev/null
+++ b/sound/soc/tegra/tegra20_das.c
@@ -0,0 +1,333 @@
1/*
2 * tegra20_das.c - Tegra20 DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, 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/debugfs.h>
25#include <linux/device.h>
26#include <linux/platform_device.h>
27#include <linux/seq_file.h>
28#include <linux/slab.h>
29#include <linux/io.h>
30#include <mach/iomap.h>
31#include <mach/pinmux.h>
32#include <sound/soc.h>
33#include "tegra20_das.h"
34
35#define DRV_NAME "tegra20-das"
36
37static struct tegra20_das *das;
38
39static inline void tegra20_das_write(u32 reg, u32 val)
40{
41#ifdef CONFIG_PM
42 das->reg_cache[reg >> 2] = val;
43#endif
44 __raw_writel(val, das->regs + reg);
45}
46
47static inline u32 tegra20_das_read(u32 reg)
48{
49 return __raw_readl(das->regs + reg);
50}
51
52#ifdef CONFIG_PM
53int tegra20_das_resume()
54{
55 int i, reg;
56
57 for (i = 0; i <= TEGRA20_DAS_DAP_ID_5; i++)
58 tegra20_das_write(i << 2, das->reg_cache[i]);
59
60 for (i = 0; i <= TEGRA20_DAS_DAC_ID_3; i++) {
61 reg = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
62 (i * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
63 tegra20_das_write(reg, das->reg_cache[reg >> 2]);
64 }
65
66 return 0;
67}
68#endif
69
70int tegra20_das_set_tristate(int dap_id, int is_tristate)
71{
72 enum tegra_pingroup pin;
73 enum tegra_tristate tristate;
74
75 switch (dap_id) {
76 case TEGRA20_DAS_DAP_ID_1:
77 pin = TEGRA_PINGROUP_DAP1;
78 break;
79 case TEGRA20_DAS_DAP_ID_2:
80 pin = TEGRA_PINGROUP_DAP2;
81 break;
82 case TEGRA20_DAS_DAP_ID_3:
83 pin = TEGRA_PINGROUP_DAP3;
84 break;
85 case TEGRA20_DAS_DAP_ID_4:
86 pin = TEGRA_PINGROUP_DAP4;
87 break;
88 default:
89 return -EINVAL;
90 }
91
92 if (is_tristate)
93 tristate = TEGRA_TRI_TRISTATE;
94 else
95 tristate = TEGRA_TRI_NORMAL;
96
97 tegra_pinmux_set_tristate(pin, tristate);
98}
99EXPORT_SYMBOL_GPL(tegra20_das_set_tristate);
100
101int tegra20_das_connect_dap_to_dac(int dap, int dac)
102{
103 u32 addr;
104 u32 reg;
105
106 if (!das)
107 return -ENODEV;
108
109 addr = TEGRA20_DAS_DAP_CTRL_SEL +
110 (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
111 reg = dac << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
112
113 tegra20_das_write(addr, reg);
114
115 return 0;
116}
117EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dac);
118
119int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master,
120 int sdata1rx, int sdata2rx)
121{
122 u32 addr;
123 u32 reg;
124
125 if (!das)
126 return -ENODEV;
127
128 addr = TEGRA20_DAS_DAP_CTRL_SEL +
129 (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
130 reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
131 !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
132 !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
133 !!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
134
135 tegra20_das_write(addr, reg);
136
137 return 0;
138}
139EXPORT_SYMBOL_GPL(tegra20_das_connect_dap_to_dap);
140
141int tegra20_das_connect_dac_to_dap(int dac, int dap)
142{
143 u32 addr;
144 u32 reg;
145
146 if (!das)
147 return -ENODEV;
148
149 addr = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
150 (dac * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
151 reg = dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
152 dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
153 dap << TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
154
155 tegra20_das_write(addr, reg);
156
157 return 0;
158}
159EXPORT_SYMBOL_GPL(tegra20_das_connect_dac_to_dap);
160
161#ifdef CONFIG_DEBUG_FS
162static int tegra20_das_show(struct seq_file *s, void *unused)
163{
164 int i;
165 u32 addr;
166 u32 reg;
167
168 for (i = 0; i < TEGRA20_DAS_DAP_CTRL_SEL_COUNT; i++) {
169 addr = TEGRA20_DAS_DAP_CTRL_SEL +
170 (i * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
171 reg = tegra20_das_read(addr);
172 seq_printf(s, "TEGRA20_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg);
173 }
174
175 for (i = 0; i < TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) {
176 addr = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
177 (i * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
178 reg = tegra20_das_read(addr);
179 seq_printf(s, "TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n",
180 i, reg);
181 }
182
183 return 0;
184}
185
186static int tegra20_das_debug_open(struct inode *inode, struct file *file)
187{
188 return single_open(file, tegra20_das_show, inode->i_private);
189}
190
191static const struct file_operations tegra20_das_debug_fops = {
192 .open = tegra20_das_debug_open,
193 .read = seq_read,
194 .llseek = seq_lseek,
195 .release = single_release,
196};
197
198static void tegra20_das_debug_add(struct tegra20_das *das)
199{
200 das->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
201 snd_soc_debugfs_root, das,
202 &tegra20_das_debug_fops);
203}
204
205static void tegra20_das_debug_remove(struct tegra20_das *das)
206{
207 if (das->debug)
208 debugfs_remove(das->debug);
209}
210#else
211static inline void tegra20_das_debug_add(struct tegra20_das *das)
212{
213}
214
215static inline void tegra20_das_debug_remove(struct tegra20_das *das)
216{
217}
218#endif
219
220static int __devinit tegra20_das_probe(struct platform_device *pdev)
221{
222 struct resource *res, *region;
223 int ret = 0;
224#ifdef CONFIG_PM
225 int i, reg;
226#endif
227
228 if (das)
229 return -ENODEV;
230
231 das = kzalloc(sizeof(struct tegra20_das), GFP_KERNEL);
232 if (!das) {
233 dev_err(&pdev->dev, "Can't allocate tegra20_das\n");
234 ret = -ENOMEM;
235 goto exit;
236 }
237 das->dev = &pdev->dev;
238
239 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
240 if (!res) {
241 dev_err(&pdev->dev, "No memory resource\n");
242 ret = -ENODEV;
243 goto err_free;
244 }
245
246 region = request_mem_region(res->start, resource_size(res),
247 pdev->name);
248 if (!region) {
249 dev_err(&pdev->dev, "Memory region already claimed\n");
250 ret = -EBUSY;
251 goto err_free;
252 }
253
254 das->regs = ioremap(res->start, resource_size(res));
255 if (!das->regs) {
256 dev_err(&pdev->dev, "ioremap failed\n");
257 ret = -ENOMEM;
258 goto err_release;
259 }
260
261#ifdef CONFIG_PM
262 /* populate the das reg cache with POR values*/
263 for (i = 0; i <= TEGRA20_DAS_DAP_ID_5; i++)
264 das->reg_cache[i] = tegra20_das_read(i << 2);
265
266 for (i = 0; i <= TEGRA20_DAS_DAC_ID_3; i++) {
267 reg = TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL +
268 (i * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
269 das->reg_cache[reg >> 2] = tegra20_das_read(reg);
270 }
271#endif
272
273 tegra20_das_debug_add(das);
274
275 platform_set_drvdata(pdev, das);
276
277 return 0;
278
279err_release:
280 release_mem_region(res->start, resource_size(res));
281err_free:
282 kfree(das);
283 das = 0;
284exit:
285 return ret;
286}
287
288static int __devexit tegra20_das_remove(struct platform_device *pdev)
289{
290 struct resource *res;
291
292 if (!das)
293 return -ENODEV;
294
295 platform_set_drvdata(pdev, NULL);
296
297 tegra20_das_debug_remove(das);
298
299 iounmap(das->regs);
300
301 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
302 release_mem_region(res->start, resource_size(res));
303
304 kfree(das);
305 das = 0;
306
307 return 0;
308}
309
310static struct platform_driver tegra20_das_driver = {
311 .probe = tegra20_das_probe,
312 .remove = __devexit_p(tegra20_das_remove),
313 .driver = {
314 .name = DRV_NAME,
315 },
316};
317
318static int __init tegra20_das_modinit(void)
319{
320 return platform_driver_register(&tegra20_das_driver);
321}
322module_init(tegra20_das_modinit);
323
324static void __exit tegra20_das_modexit(void)
325{
326 platform_driver_unregister(&tegra20_das_driver);
327}
328module_exit(tegra20_das_modexit);
329
330MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
331MODULE_DESCRIPTION("Tegra DAS driver");
332MODULE_LICENSE("GPL");
333MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h
new file mode 100644
index 00000000000..0d58c7d1bc3
--- /dev/null
+++ b/sound/soc/tegra/tegra20_das.h
@@ -0,0 +1,148 @@
1/*
2 * tegra20_das.h - Definitions for Tegra20 DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, 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#ifndef __TEGRA20_DAS_H__
24#define __TEGRA20_DAS_H__
25
26/* Register TEGRA20_DAS_DAP_CTRL_SEL */
27#define TEGRA20_DAS_DAP_CTRL_SEL 0x00
28#define TEGRA20_DAS_DAP_CTRL_SEL_COUNT 5
29#define TEGRA20_DAS_DAP_CTRL_SEL_STRIDE 4
30#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31
31#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1
32#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30
33#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1
34#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29
35#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1
36#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0
37#define TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5
38
39/* Values for field TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
40#define TEGRA20_DAS_DAP_SEL_DAC1 0
41#define TEGRA20_DAS_DAP_SEL_DAC2 1
42#define TEGRA20_DAS_DAP_SEL_DAC3 2
43#define TEGRA20_DAS_DAP_SEL_DAP1 16
44#define TEGRA20_DAS_DAP_SEL_DAP2 17
45#define TEGRA20_DAS_DAP_SEL_DAP3 18
46#define TEGRA20_DAS_DAP_SEL_DAP4 19
47#define TEGRA20_DAS_DAP_SEL_DAP5 20
48
49/* Register TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL */
50#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL 0x40
51#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3
52#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4
53#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28
54#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4
55#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24
56#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4
57#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0
58#define TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4
59
60/*
61 * Values for:
62 * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
63 * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
64 * TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
65 */
66#define TEGRA20_DAS_DAC_SEL_DAP1 0
67#define TEGRA20_DAS_DAC_SEL_DAP2 1
68#define TEGRA20_DAS_DAC_SEL_DAP3 2
69#define TEGRA20_DAS_DAC_SEL_DAP4 3
70#define TEGRA20_DAS_DAC_SEL_DAP5 4
71
72/*
73 * Names/IDs of the DACs/DAPs.
74 */
75
76#define TEGRA20_DAS_DAP_ID_1 0
77#define TEGRA20_DAS_DAP_ID_2 1
78#define TEGRA20_DAS_DAP_ID_3 2
79#define TEGRA20_DAS_DAP_ID_4 3
80#define TEGRA20_DAS_DAP_ID_5 4
81
82#define TEGRA20_DAS_DAC_ID_1 0
83#define TEGRA20_DAS_DAC_ID_2 1
84#define TEGRA20_DAS_DAC_ID_3 2
85
86#ifdef CONFIG_PM
87#define TEGRA20_DAS_CACHE_SIZE ((((TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL) + (TEGRA20_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE*TEGRA20_DAS_DAC_ID_3))>>2) + 1)
88#endif
89
90struct tegra20_das {
91 struct device *dev;
92 void __iomem *regs;
93 struct dentry *debug;
94#ifdef CONFIG_PM
95 u32 reg_cache[TEGRA20_DAS_CACHE_SIZE];
96#endif
97};
98
99#ifdef CONFIG_PM
100/* Restores the das registers from cache */
101extern int tegra20_das_resume();
102#endif
103/*
104 * Terminology:
105 * DAS: Digital audio switch (HW module controlled by this driver)
106 * DAP: Digital audio port (port/pins on Tegra device)
107 * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
108 *
109 * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
110 * DAC, or another DAP. When DAPs are connected, one must be the master and
111 * one the slave. Each DAC allows selection of a specific DAP for input, to
112 * cater for the case where N DAPs are connected to 1 DAC for broadcast
113 * output.
114 *
115 * This driver is dumb; no attempt is made to ensure that a valid routing
116 * configuration is programmed.
117 */
118
119/*
120 * Connect a DAP to to a DAC
121 * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_*
122 * dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC*
123 */
124extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel);
125
126/*
127 * Connect a DAP to to another DAP
128 * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_*
129 * other_dap_sel: DAP to connect to: TEGRA20_DAS_DAP_SEL_DAP*
130 * master: Is this DAP the master (1) or slave (0)
131 * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
132 * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
133 */
134extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
135 int master, int sdata1rx,
136 int sdata2rx);
137
138/*
139 * Connect a DAC's input to a DAP
140 * (DAC outputs are selected by the DAP)
141 * dac_id: DAC ID to connect: TEGRA20_DAS_DAC_ID_*
142 * dap_sel: DAP to receive input from: TEGRA20_DAS_DAC_SEL_DAP*
143 */
144extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel);
145
146extern int tegra20_das_set_tristate(int dap_id, int is_tristate);
147
148#endif
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
new file mode 100644
index 00000000000..e6de1c07a39
--- /dev/null
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -0,0 +1,586 @@
1/*
2 * tegra20_i2s.c - Tegra20 I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30#include <asm/mach-types.h>
31#include <linux/clk.h>
32#include <linux/module.h>
33#include <linux/debugfs.h>
34#include <linux/device.h>
35#include <linux/platform_device.h>
36#include <linux/seq_file.h>
37#include <linux/slab.h>
38#include <linux/io.h>
39#include <mach/iomap.h>
40#include <sound/core.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "tegra20_das.h"
46#include "tegra20_i2s.h"
47
48#define DRV_NAME "tegra20-i2s"
49
50static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
51{
52#ifdef CONFIG_PM
53 i2s->reg_cache[reg >> 2] = val;
54#endif
55 __raw_writel(val, i2s->regs + reg);
56}
57
58static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
59{
60 return __raw_readl(i2s->regs + reg);
61}
62
63#ifdef CONFIG_DEBUG_FS
64static int tegra20_i2s_show(struct seq_file *s, void *unused)
65{
66#define REG(r) { r, #r }
67 static const struct {
68 int offset;
69 const char *name;
70 } regs[] = {
71 REG(TEGRA20_I2S_CTRL),
72 REG(TEGRA20_I2S_STATUS),
73 REG(TEGRA20_I2S_TIMING),
74 REG(TEGRA20_I2S_FIFO_SCR),
75 REG(TEGRA20_I2S_PCM_CTRL),
76 REG(TEGRA20_I2S_NW_CTRL),
77 REG(TEGRA20_I2S_TDM_CTRL),
78 REG(TEGRA20_I2S_TDM_TX_RX_CTRL),
79 };
80#undef REG
81
82 struct tegra20_i2s *i2s = s->private;
83 int i;
84
85 clk_enable(i2s->clk_i2s);
86
87 for (i = 0; i < ARRAY_SIZE(regs); i++) {
88 u32 val = tegra20_i2s_read(i2s, regs[i].offset);
89 seq_printf(s, "%s = %08x\n", regs[i].name, val);
90 }
91
92 clk_disable(i2s->clk_i2s);
93
94 return 0;
95}
96
97static int tegra20_i2s_debug_open(struct inode *inode, struct file *file)
98{
99 return single_open(file, tegra20_i2s_show, inode->i_private);
100}
101
102static const struct file_operations tegra20_i2s_debug_fops = {
103 .open = tegra20_i2s_debug_open,
104 .read = seq_read,
105 .llseek = seq_lseek,
106 .release = single_release,
107};
108
109static void tegra20_i2s_debug_add(struct tegra20_i2s *i2s, int id)
110{
111 char name[] = DRV_NAME ".0";
112
113 snprintf(name, sizeof(name), DRV_NAME".%1d", id);
114 i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
115 i2s, &tegra20_i2s_debug_fops);
116}
117
118static void tegra20_i2s_debug_remove(struct tegra20_i2s *i2s)
119{
120 if (i2s->debug)
121 debugfs_remove(i2s->debug);
122}
123#else
124static inline void tegra20_i2s_debug_add(struct tegra20_i2s *i2s, int id)
125{
126}
127
128static inline void tegra20_i2s_debug_remove(struct tegra20_i2s *i2s)
129{
130}
131#endif
132
133static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
134 unsigned int fmt)
135{
136 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
137
138 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
139 case SND_SOC_DAIFMT_NB_NF:
140 break;
141 default:
142 return -EINVAL;
143 }
144
145 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE;
146 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
147 case SND_SOC_DAIFMT_CBS_CFS:
148 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
149 break;
150 case SND_SOC_DAIFMT_CBM_CFM:
151 break;
152 default:
153 return -EINVAL;
154 }
155
156 i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
157 TEGRA20_I2S_CTRL_LRCK_MASK);
158 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
159 case SND_SOC_DAIFMT_DSP_A:
160 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
161 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
162 break;
163 case SND_SOC_DAIFMT_DSP_B:
164 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
165 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
166 break;
167 case SND_SOC_DAIFMT_I2S:
168 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
169 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
170 break;
171 case SND_SOC_DAIFMT_RIGHT_J:
172 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
173 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
174 break;
175 case SND_SOC_DAIFMT_LEFT_J:
176 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
177 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
178 break;
179 default:
180 return -EINVAL;
181 }
182
183 return 0;
184}
185
186static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
187 struct snd_pcm_hw_params *params,
188 struct snd_soc_dai *dai)
189{
190 struct device *dev = substream->pcm->card->dev;
191 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
192 u32 reg;
193 int ret, sample_size, srate, i2sclock, bitcnt, i2sclk_div;
194
195 if ((i2s->reg_ctrl & TEGRA20_I2S_CTRL_BIT_FORMAT_I2S) &&
196 (params_channels(params) != 2)) {
197 dev_err(dev, "Only Stereo is supported in I2s mode\n");
198 return -EINVAL;
199 }
200
201 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
202 switch (params_format(params)) {
203 case SNDRV_PCM_FORMAT_S16_LE:
204 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16;
205 sample_size = 16;
206 break;
207 case SNDRV_PCM_FORMAT_S24_LE:
208 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24;
209 sample_size = 24;
210 break;
211 case SNDRV_PCM_FORMAT_S32_LE:
212 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32;
213 sample_size = 32;
214 break;
215 default:
216 return -EINVAL;
217 }
218
219 srate = params_rate(params);
220
221 /* Final "* 2" required by Tegra hardware */
222 i2sclock = srate * params_channels(params) * sample_size * 2;
223
224 /* Additional "* 2" is needed for DSP mode */
225 if (i2s->reg_ctrl & TEGRA20_I2S_CTRL_BIT_FORMAT_DSP && !machine_is_whistler())
226 i2sclock *= 2;
227
228 ret = clk_set_rate(i2s->clk_i2s, i2sclock);
229 if (ret) {
230 dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
231 return ret;
232 }
233
234 if (i2s->reg_ctrl & TEGRA20_I2S_CTRL_BIT_FORMAT_DSP)
235 i2sclk_div = srate;
236 else
237 i2sclk_div = params_channels(params) * srate;
238
239 bitcnt = (i2sclock / i2sclk_div) - 1;
240
241 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
242 return -EINVAL;
243 reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
244
245 if (i2sclock % i2sclk_div)
246 reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
247
248 clk_enable(i2s->clk_i2s);
249
250 tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg);
251
252 if (sample_size * params_channels(params) >= 32)
253 tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
254 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
255 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
256 else
257 tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
258 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS |
259 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS);
260
261 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
262 reg = tegra20_i2s_read(i2s, TEGRA20_I2S_PCM_CTRL);
263 if (i2s->reg_ctrl & TEGRA20_I2S_CTRL_BIT_FORMAT_DSP) {
264 if (sample_size == 16)
265 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_16_LSB;
266 else if (sample_size == 24)
267 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_24_LSB;
268 else
269 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_32;
270
271 i2s->capture_dma_data.width = sample_size;
272 i2s->playback_dma_data.width = sample_size;
273
274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
275 reg |= TEGRA20_I2S_PCM_CTRL_TRM_MODE_EN;
276 else
277 reg |= TEGRA20_I2S_PCM_CTRL_RCV_MODE_EN;
278 } else {
279 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
280 i2s->capture_dma_data.width = 32;
281 i2s->playback_dma_data.width = 32;
282 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
283 reg &= ~TEGRA20_I2S_PCM_CTRL_TRM_MODE_EN;
284 else
285 reg &= ~TEGRA20_I2S_PCM_CTRL_RCV_MODE_EN;
286 }
287 tegra20_i2s_write(i2s, TEGRA20_I2S_PCM_CTRL, reg);
288
289 clk_disable(i2s->clk_i2s);
290
291 return 0;
292}
293
294static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
295{
296 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE;
297 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
298}
299
300static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
301{
302 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE;
303 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
304}
305
306static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
307{
308 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE;
309 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
310}
311
312static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
313{
314 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE;
315 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
316}
317
318static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
319 struct snd_soc_dai *dai)
320{
321 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
322
323 switch (cmd) {
324 case SNDRV_PCM_TRIGGER_START:
325 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
326 case SNDRV_PCM_TRIGGER_RESUME:
327 clk_enable(i2s->clk_i2s);
328 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
329 tegra20_i2s_start_playback(i2s);
330 else
331 tegra20_i2s_start_capture(i2s);
332 break;
333 case SNDRV_PCM_TRIGGER_STOP:
334 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
335 case SNDRV_PCM_TRIGGER_SUSPEND:
336 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
337 tegra20_i2s_stop_playback(i2s);
338 else
339 tegra20_i2s_stop_capture(i2s);
340 clk_disable(i2s->clk_i2s);
341 break;
342 default:
343 return -EINVAL;
344 }
345
346 return 0;
347}
348
349static int tegra20_i2s_probe(struct snd_soc_dai *dai)
350{
351 struct tegra20_i2s * i2s = snd_soc_dai_get_drvdata(dai);
352#ifdef CONFIG_PM
353 int i;
354#endif
355
356 dai->capture_dma_data = &i2s->capture_dma_data;
357 dai->playback_dma_data = &i2s->playback_dma_data;
358
359#ifdef CONFIG_PM
360 /* populate the i2s reg cache with POR values*/
361 clk_enable(i2s->clk_i2s);
362
363 for (i = 0; i < ((TEGRA20_I2S_TDM_TX_RX_CTRL >> 2) + 1); i++) {
364 if ((i == TEGRA20_I2S_CACHE_RSVD_6) ||
365 (i == TEGRA20_I2S_CACHE_RSVD_7))
366 continue;
367
368 i2s->reg_cache[i] = tegra20_i2s_read(i2s, i << 2);
369 }
370
371 clk_disable(i2s->clk_i2s);
372#endif
373
374 return 0;
375}
376
377#ifdef CONFIG_PM
378int tegra20_i2s_resume(struct snd_soc_dai *cpu_dai)
379{
380 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
381 int i;
382
383 clk_enable(i2s->clk_i2s);
384
385 /*restore the i2s regs*/
386 for (i = 0; i < ((TEGRA20_I2S_TDM_TX_RX_CTRL >> 2) + 1); i++) {
387 if ((i == TEGRA20_I2S_CACHE_RSVD_6) ||
388 (i == TEGRA20_I2S_CACHE_RSVD_7))
389 continue;
390
391 tegra20_i2s_write(i2s, i << 2, i2s->reg_cache[i]);
392 }
393
394 /*restore the das regs*/
395 tegra20_das_resume();
396
397 clk_disable(i2s->clk_i2s);
398
399 return 0;
400}
401#else
402#define tegra20_i2s_resume NULL
403#endif
404
405static struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
406 .set_fmt = tegra20_i2s_set_fmt,
407 .hw_params = tegra20_i2s_hw_params,
408 .trigger = tegra20_i2s_trigger,
409};
410
411struct snd_soc_dai_driver tegra20_i2s_dai[] = {
412 {
413 .name = DRV_NAME ".0",
414 .probe = tegra20_i2s_probe,
415 .resume = tegra20_i2s_resume,
416 .playback = {
417 .channels_min = 1,
418 .channels_max = 2,
419 .rates = SNDRV_PCM_RATE_8000_96000,
420 .formats = SNDRV_PCM_FMTBIT_S16_LE,
421 },
422 .capture = {
423 .channels_min = 1,
424 .channels_max = 2,
425 .rates = SNDRV_PCM_RATE_8000_96000,
426 .formats = SNDRV_PCM_FMTBIT_S16_LE,
427 },
428 .ops = &tegra20_i2s_dai_ops,
429 .symmetric_rates = 1,
430 },
431 {
432 .name = DRV_NAME ".1",
433 .probe = tegra20_i2s_probe,
434 .resume = tegra20_i2s_resume,
435 .playback = {
436 .channels_min = 1,
437 .channels_max = 2,
438 .rates = SNDRV_PCM_RATE_8000_96000,
439 .formats = SNDRV_PCM_FMTBIT_S16_LE,
440 },
441 .capture = {
442 .channels_min = 1,
443 .channels_max = 2,
444 .rates = SNDRV_PCM_RATE_8000_96000,
445 .formats = SNDRV_PCM_FMTBIT_S16_LE,
446 },
447 .ops = &tegra20_i2s_dai_ops,
448 .symmetric_rates = 1,
449 },
450};
451
452static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
453{
454 struct tegra20_i2s * i2s;
455 struct resource *mem, *memregion, *dmareq;
456 int ret;
457
458 if ((pdev->id < 0) ||
459 (pdev->id >= ARRAY_SIZE(tegra20_i2s_dai))) {
460 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
461 return -EINVAL;
462 }
463
464 i2s = kzalloc(sizeof(struct tegra20_i2s), GFP_KERNEL);
465 if (!i2s) {
466 dev_err(&pdev->dev, "Can't allocate tegra20_i2s\n");
467 ret = -ENOMEM;
468 goto exit;
469 }
470 dev_set_drvdata(&pdev->dev, i2s);
471
472 i2s->clk_i2s = clk_get(&pdev->dev, NULL);
473 if (IS_ERR(i2s->clk_i2s)) {
474 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
475 ret = PTR_ERR(i2s->clk_i2s);
476 goto err_free;
477 }
478
479 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
480 if (!mem) {
481 dev_err(&pdev->dev, "No memory resource\n");
482 ret = -ENODEV;
483 goto err_clk_put;
484 }
485
486 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
487 if (!dmareq) {
488 dev_err(&pdev->dev, "No DMA resource\n");
489 ret = -ENODEV;
490 goto err_clk_put;
491 }
492
493 memregion = request_mem_region(mem->start, resource_size(mem),
494 DRV_NAME);
495 if (!memregion) {
496 dev_err(&pdev->dev, "Memory region already claimed\n");
497 ret = -EBUSY;
498 goto err_clk_put;
499 }
500
501 i2s->regs = ioremap(mem->start, resource_size(mem));
502 if (!i2s->regs) {
503 dev_err(&pdev->dev, "ioremap failed\n");
504 ret = -ENOMEM;
505 goto err_release;
506 }
507
508 i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
509 i2s->capture_dma_data.wrap = 4;
510 i2s->capture_dma_data.width = 32;
511 i2s->capture_dma_data.req_sel = dmareq->start;
512
513 i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
514 i2s->playback_dma_data.wrap = 4;
515 i2s->playback_dma_data.width = 32;
516 i2s->playback_dma_data.req_sel = dmareq->start;
517
518 ret = snd_soc_register_dai(&pdev->dev, &tegra20_i2s_dai[pdev->id]);
519 if (ret) {
520 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
521 ret = -ENOMEM;
522 goto err_unmap;
523 }
524
525 tegra20_i2s_debug_add(i2s, pdev->id);
526
527 return 0;
528
529err_unmap:
530 iounmap(i2s->regs);
531err_release:
532 release_mem_region(mem->start, resource_size(mem));
533err_clk_put:
534 clk_put(i2s->clk_i2s);
535err_free:
536 kfree(i2s);
537exit:
538 return ret;
539}
540
541static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
542{
543 struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
544 struct resource *res;
545
546 snd_soc_unregister_dai(&pdev->dev);
547
548 tegra20_i2s_debug_remove(i2s);
549
550 iounmap(i2s->regs);
551
552 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
553 release_mem_region(res->start, resource_size(res));
554
555 clk_put(i2s->clk_i2s);
556
557 kfree(i2s);
558
559 return 0;
560}
561
562static struct platform_driver tegra20_i2s_driver = {
563 .driver = {
564 .name = DRV_NAME,
565 .owner = THIS_MODULE,
566 },
567 .probe = tegra20_i2s_platform_probe,
568 .remove = __devexit_p(tegra20_i2s_platform_remove),
569};
570
571static int __init snd_tegra20_i2s_init(void)
572{
573 return platform_driver_register(&tegra20_i2s_driver);
574}
575module_init(snd_tegra20_i2s_init);
576
577static void __exit snd_tegra20_i2s_exit(void)
578{
579 platform_driver_unregister(&tegra20_i2s_driver);
580}
581module_exit(snd_tegra20_i2s_exit);
582
583MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
584MODULE_DESCRIPTION("Tegra I2S ASoC driver");
585MODULE_LICENSE("GPL");
586MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
new file mode 100644
index 00000000000..ded0c8dee02
--- /dev/null
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -0,0 +1,198 @@
1/*
2 * tegra20_i2s.h - Definitions for Tegra20 I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#ifndef __TEGRA20_I2S_H__
32#define __TEGRA20_I2S_H__
33
34#include "tegra_pcm.h"
35
36/* Register offsets from TEGRA20_I2S1_BASE and TEGRA20_I2S2_BASE */
37
38#define TEGRA20_I2S_CTRL 0x00
39#define TEGRA20_I2S_STATUS 0x04
40#define TEGRA20_I2S_TIMING 0x08
41#define TEGRA20_I2S_FIFO_SCR 0x0c
42#define TEGRA20_I2S_PCM_CTRL 0x10
43#define TEGRA20_I2S_NW_CTRL 0x14
44#define TEGRA20_I2S_TDM_CTRL 0x20
45#define TEGRA20_I2S_TDM_TX_RX_CTRL 0x24
46#define TEGRA20_I2S_FIFO1 0x40
47#define TEGRA20_I2S_FIFO2 0x80
48
49/* Fields in TEGRA20_I2S_CTRL */
50
51#define TEGRA20_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30)
52#define TEGRA20_I2S_CTRL_FIFO1_ENABLE (1 << 29)
53#define TEGRA20_I2S_CTRL_FIFO2_ENABLE (1 << 28)
54#define TEGRA20_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27)
55#define TEGRA20_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26)
56#define TEGRA20_I2S_CTRL_MASTER_ENABLE (1 << 25)
57
58#define TEGRA20_I2S_LRCK_LEFT_LOW 0
59#define TEGRA20_I2S_LRCK_RIGHT_LOW 1
60
61#define TEGRA20_I2S_CTRL_LRCK_SHIFT 24
62#define TEGRA20_I2S_CTRL_LRCK_MASK (1 << TEGRA20_I2S_CTRL_LRCK_SHIFT)
63#define TEGRA20_I2S_CTRL_LRCK_L_LOW (TEGRA20_I2S_LRCK_LEFT_LOW << TEGRA20_I2S_CTRL_LRCK_SHIFT)
64#define TEGRA20_I2S_CTRL_LRCK_R_LOW (TEGRA20_I2S_LRCK_RIGHT_LOW << TEGRA20_I2S_CTRL_LRCK_SHIFT)
65
66#define TEGRA20_I2S_BIT_FORMAT_I2S 0
67#define TEGRA20_I2S_BIT_FORMAT_RJM 1
68#define TEGRA20_I2S_BIT_FORMAT_LJM 2
69#define TEGRA20_I2S_BIT_FORMAT_DSP 3
70
71#define TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT 10
72#define TEGRA20_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
73#define TEGRA20_I2S_CTRL_BIT_FORMAT_I2S (TEGRA20_I2S_BIT_FORMAT_I2S << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
74#define TEGRA20_I2S_CTRL_BIT_FORMAT_RJM (TEGRA20_I2S_BIT_FORMAT_RJM << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
75#define TEGRA20_I2S_CTRL_BIT_FORMAT_LJM (TEGRA20_I2S_BIT_FORMAT_LJM << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
76#define TEGRA20_I2S_CTRL_BIT_FORMAT_DSP (TEGRA20_I2S_BIT_FORMAT_DSP << TEGRA20_I2S_CTRL_BIT_FORMAT_SHIFT)
77
78#define TEGRA20_I2S_BIT_SIZE_16 0
79#define TEGRA20_I2S_BIT_SIZE_20 1
80#define TEGRA20_I2S_BIT_SIZE_24 2
81#define TEGRA20_I2S_BIT_SIZE_32 3
82
83#define TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT 8
84#define TEGRA20_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
85#define TEGRA20_I2S_CTRL_BIT_SIZE_16 (TEGRA20_I2S_BIT_SIZE_16 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
86#define TEGRA20_I2S_CTRL_BIT_SIZE_20 (TEGRA20_I2S_BIT_SIZE_20 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
87#define TEGRA20_I2S_CTRL_BIT_SIZE_24 (TEGRA20_I2S_BIT_SIZE_24 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
88#define TEGRA20_I2S_CTRL_BIT_SIZE_32 (TEGRA20_I2S_BIT_SIZE_32 << TEGRA20_I2S_CTRL_BIT_SIZE_SHIFT)
89
90#define TEGRA20_I2S_FIFO_16_LSB 0
91#define TEGRA20_I2S_FIFO_20_LSB 1
92#define TEGRA20_I2S_FIFO_24_LSB 2
93#define TEGRA20_I2S_FIFO_32 3
94#define TEGRA20_I2S_FIFO_PACKED 7
95
96#define TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT 4
97#define TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
98#define TEGRA20_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA20_I2S_FIFO_16_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
99#define TEGRA20_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA20_I2S_FIFO_20_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
100#define TEGRA20_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA20_I2S_FIFO_24_LSB << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
101#define TEGRA20_I2S_CTRL_FIFO_FORMAT_32 (TEGRA20_I2S_FIFO_32 << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
102#define TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA20_I2S_FIFO_PACKED << TEGRA20_I2S_CTRL_FIFO_FORMAT_SHIFT)
103
104#define TEGRA20_I2S_CTRL_IE_FIFO1_ERR (1 << 3)
105#define TEGRA20_I2S_CTRL_IE_FIFO2_ERR (1 << 2)
106#define TEGRA20_I2S_CTRL_QE_FIFO1 (1 << 1)
107#define TEGRA20_I2S_CTRL_QE_FIFO2 (1 << 0)
108
109/* Fields in TEGRA20_I2S_STATUS */
110
111#define TEGRA20_I2S_STATUS_FIFO1_RDY (1 << 31)
112#define TEGRA20_I2S_STATUS_FIFO2_RDY (1 << 30)
113#define TEGRA20_I2S_STATUS_FIFO1_BSY (1 << 29)
114#define TEGRA20_I2S_STATUS_FIFO2_BSY (1 << 28)
115#define TEGRA20_I2S_STATUS_FIFO1_ERR (1 << 3)
116#define TEGRA20_I2S_STATUS_FIFO2_ERR (1 << 2)
117#define TEGRA20_I2S_STATUS_QS_FIFO1 (1 << 1)
118#define TEGRA20_I2S_STATUS_QS_FIFO2 (1 << 0)
119
120/* Fields in TEGRA20_I2S_TIMING */
121
122#define TEGRA20_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
123#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
124#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
125#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
126
127/* Fields in TEGRA20_I2S_FIFO_SCR */
128
129#define TEGRA20_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24
130#define TEGRA20_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16
131#define TEGRA20_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f
132
133#define TEGRA20_I2S_FIFO_SCR_FIFO2_CLR (1 << 12)
134#define TEGRA20_I2S_FIFO_SCR_FIFO1_CLR (1 << 8)
135
136#define TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT 0
137#define TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1
138#define TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2
139#define TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3
140
141#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4
142#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
143#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
144#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
145#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
146#define TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
147
148#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0
149#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
150#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA20_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
151#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
152#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
153#define TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA20_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
154
155/* Fields in TEGRA20_I2S_PCM_CTRL */
156
157#define TEGRA20_I2S_PCM_TX_POS_EDGE_NO_HIGHZ 0
158#define TEGRA20_I2S_PCM_TX_POS_EDGE_HIGHZ 1
159#define TEGRA20_I2S_PCM_TX_NEG_EDGE_NO_HIGHZ 2
160#define TEGRA20_I2S_PCM_TX_NEG_EDGE_HIGHZ 3
161
162#define TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT 9
163#define TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_MASK (0x3 << TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT)
164#define TEGRA20_I2S_PCM_CTRL_TX_POS_EDGE_NO_HIGHZ (TEGRA20_I2S_PCM_TX_POS_EDGE_NO_HIGHZ << TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT)
165#define TEGRA20_I2S_PCM_CTRL_TX_POS_EDGE_HIGHZ (TEGRA20_I2S_PCM_TX_POS_EDGE_HIGHZ << TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT)
166#define TEGRA20_I2S_PCM_CTRL_TX_NEG_EDGE_NO_HIGHZ (TEGRA20_I2S_PCM_TX_NEG_EDGE_NO_HIGHZ << TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT)
167#define TEGRA20_I2S_PCM_CTRL_TX_NEG_EDGE_HIGHZ (TEGRA20_I2S_PCM_TX_NEG_EDGE_HIGHZ << TEGRA20_I2S_PCM_CTRL_TX_EDGE_CTRL_SHIFT)
168
169#define TEGRA20_I2S_PCM_CTRL_TX_MASK_BITS_SHIFT 6
170#define TEGRA20_I2S_PCM_CTRL_TX_MASK_BITS_MASK (0x7 << TEGRA20_I2S_PCM_CTRL_TX_MASK_BITS_SHIFT)
171
172#define TEGRA20_I2S_PCM_CTRL_FSYNC_LONG (1 << 5)
173#define TEGRA20_I2S_PCM_CTRL_TRM_MODE_EN (1 << 4)
174
175#define TEGRA20_I2S_PCM_CTRL_RX_MASK_BITS_SHIFT 1
176#define TEGRA20_I2S_PCM_CTRL_RX_MASK_BITS_MASK (0x7 << TEGRA20_I2S_PCM_CTRL_RX_MASK_BITS_SHIFT)
177
178#define TEGRA20_I2S_PCM_CTRL_RCV_MODE_EN (1 << 0)
179
180#ifdef CONFIG_PM
181/* unused cache locations for i2s reg cache */
182#define TEGRA20_I2S_CACHE_RSVD_6 ((TEGRA20_I2S_NW_CTRL>>2) + 1)
183#define TEGRA20_I2S_CACHE_RSVD_7 (TEGRA20_I2S_CACHE_RSVD_6 + 1)
184#endif
185
186struct tegra20_i2s {
187 struct clk *clk_i2s;
188 struct tegra_pcm_dma_params capture_dma_data;
189 struct tegra_pcm_dma_params playback_dma_data;
190 void __iomem *regs;
191 struct dentry *debug;
192 u32 reg_ctrl;
193#ifdef CONFIG_PM
194 u32 reg_cache[(TEGRA20_I2S_TDM_TX_RX_CTRL >> 2) + 1];
195#endif
196};
197
198#endif
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
new file mode 100644
index 00000000000..3e747b5e193
--- /dev/null
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -0,0 +1,463 @@
1/*
2 * tegra20_spdif.c - Tegra20 SPDIF driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, 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/clk.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/device.h>
27#include <linux/platform_device.h>
28#include <linux/seq_file.h>
29#include <linux/slab.h>
30#include <linux/io.h>
31#include <mach/iomap.h>
32#include <mach/hdmi-audio.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37
38#include "tegra20_spdif.h"
39
40#define DRV_NAME "tegra20-spdif"
41
42static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg,
43 u32 val)
44{
45#ifdef CONFIG_PM
46 if (reg < TEGRA20_SPDIF_CH_STA_TX_A)
47 spdif->reg_ctrl_cache[reg >> 2] = val;
48 else
49 spdif->reg_tx_cache[((reg - TEGRA20_SPDIF_CH_STA_TX_A) >> 2)]
50 = val;
51#endif
52 __raw_writel(val, spdif->regs + reg);
53}
54
55static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg)
56{
57 return __raw_readl(spdif->regs + reg);
58}
59
60#ifdef CONFIG_DEBUG_FS
61static int tegra20_spdif_show(struct seq_file *s, void *unused)
62{
63#define REG(r) { r, #r }
64 static const struct {
65 int offset;
66 const char *name;
67 } regs[] = {
68 REG(TEGRA20_SPDIF_CTRL),
69 REG(TEGRA20_SPDIF_STATUS),
70 REG(TEGRA20_SPDIF_STROBE_CTRL),
71 REG(TEGRA20_SPDIF_DATA_FIFO_CSR),
72 REG(TEGRA20_SPDIF_CH_STA_RX_A),
73 REG(TEGRA20_SPDIF_CH_STA_RX_B),
74 REG(TEGRA20_SPDIF_CH_STA_RX_C),
75 REG(TEGRA20_SPDIF_CH_STA_RX_D),
76 REG(TEGRA20_SPDIF_CH_STA_RX_E),
77 REG(TEGRA20_SPDIF_CH_STA_RX_F),
78 REG(TEGRA20_SPDIF_CH_STA_TX_A),
79 REG(TEGRA20_SPDIF_CH_STA_TX_B),
80 REG(TEGRA20_SPDIF_CH_STA_TX_C),
81 REG(TEGRA20_SPDIF_CH_STA_TX_D),
82 REG(TEGRA20_SPDIF_CH_STA_TX_E),
83 REG(TEGRA20_SPDIF_CH_STA_TX_F),
84 };
85#undef REG
86
87 struct tegra20_spdif *spdif = s->private;
88 int i;
89
90 for (i = 0; i < ARRAY_SIZE(regs); i++) {
91 u32 val = tegra20_spdif_read(spdif, regs[i].offset);
92 seq_printf(s, "%s = %08x\n", regs[i].name, val);
93 }
94
95 return 0;
96}
97
98static int tegra20_spdif_debug_open(struct inode *inode, struct file *file)
99{
100 return single_open(file, tegra20_spdif_show, inode->i_private);
101}
102
103static const struct file_operations tegra20_spdif_debug_fops = {
104 .open = tegra20_spdif_debug_open,
105 .read = seq_read,
106 .llseek = seq_lseek,
107 .release = single_release,
108};
109
110static void tegra20_spdif_debug_add(struct tegra20_spdif *spdif)
111{
112 spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
113 snd_soc_debugfs_root, spdif,
114 &tegra20_spdif_debug_fops);
115}
116
117static void tegra20_spdif_debug_remove(struct tegra20_spdif *spdif)
118{
119 if (spdif->debug)
120 debugfs_remove(spdif->debug);
121}
122#else
123static inline void tegra20_spdif_debug_add(struct tegra20_spdif *spdif)
124{
125}
126
127static inline void tegra20_spdif_debug_remove(struct tegra20_spdif *spdif)
128{
129}
130#endif
131
132static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params,
134 struct snd_soc_dai *dai)
135{
136 struct device *dev = substream->pcm->card->dev;
137 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
138 int ret, srate, spdifclock;
139 u32 ch_sta[2] = {0, 0};
140
141 spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK;
142 spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
143 switch (params_format(params)) {
144 case SNDRV_PCM_FORMAT_S16_LE:
145 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK;
146 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
147 break;
148 default:
149 return -EINVAL;
150 }
151
152 srate = params_rate(params);
153 ch_sta[0] = tegra20_spdif_read(spdif, TEGRA20_SPDIF_CH_STA_TX_A);
154 ch_sta[0] &= ~TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
155 ch_sta[1] = tegra20_spdif_read(spdif, TEGRA20_SPDIF_CH_STA_TX_B);
156 ch_sta[1] &= ~TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
157 switch (params_rate(params)) {
158 case 32000:
159 spdifclock = 4096000;
160 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
161 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
162 break;
163 case 44100:
164 spdifclock = 5644800;
165 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
166 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
167 break;
168 case 48000:
169 spdifclock = 6144000;
170 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
171 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
172 break;
173 case 88200:
174 spdifclock = 11289600;
175 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
176 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
177 break;
178 case 96000:
179 spdifclock = 12288000;
180 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
181 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
182 break;
183 case 176400:
184 spdifclock = 22579200;
185 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
186 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
187 break;
188 case 192000:
189 spdifclock = 24576000;
190 ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
191 ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
192 break;
193 default:
194 return -EINVAL;
195 }
196
197 ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
198 if (ret) {
199 dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
200 return ret;
201 }
202
203 clk_enable(spdif->clk_spdif_out);
204
205 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CH_STA_TX_A, ch_sta[0]);
206 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CH_STA_TX_B, ch_sta[1]);
207
208 clk_disable(spdif->clk_spdif_out);
209
210 ret = tegra_hdmi_setup_audio_freq_source(srate, SPDIF);
211 if (ret) {
212 dev_err(dev, "Can't set HDMI audio freq source: %d\n", ret);
213 return ret;
214 }
215
216 return 0;
217}
218
219static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
220{
221 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TC_EN | TEGRA20_SPDIF_CTRL_TX_EN;
222 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
223}
224
225static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
226{
227 spdif->reg_ctrl &= ~(TEGRA20_SPDIF_CTRL_TX_EN |
228 TEGRA20_SPDIF_CTRL_TC_EN);
229 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
230}
231
232static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
233 struct snd_soc_dai *dai)
234{
235 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
236
237 switch (cmd) {
238 case SNDRV_PCM_TRIGGER_START:
239 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
240 case SNDRV_PCM_TRIGGER_RESUME:
241 clk_enable(spdif->clk_spdif_out);
242 tegra20_spdif_start_playback(spdif);
243 break;
244 case SNDRV_PCM_TRIGGER_STOP:
245 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
246 case SNDRV_PCM_TRIGGER_SUSPEND:
247 tegra20_spdif_stop_playback(spdif);
248 clk_disable(spdif->clk_spdif_out);
249 break;
250 default:
251 return -EINVAL;
252 }
253
254 return 0;
255}
256
257static int tegra20_spdif_probe(struct snd_soc_dai *dai)
258{
259 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
260#ifdef CONFIG_PM
261 int i, reg;
262#endif
263
264 dai->capture_dma_data = NULL;
265 dai->playback_dma_data = &spdif->playback_dma_data;
266
267#ifdef CONFIG_PM
268 clk_enable(spdif->clk_spdif_out);
269
270 /* populate the spdif reg cache with POR values*/
271 for (i = 0; i < TEGRA20_SPDIF_CTRL_CACHE_SIZE; i++)
272 spdif->reg_ctrl_cache[i] = tegra20_spdif_read(spdif, i << 2);
273
274 for (i = 0; i < TEGRA20_SPDIF_TX_CACHE_SIZE; i++) {
275 reg = (TEGRA20_SPDIF_CH_STA_TX_A) + (i << 2);
276 spdif->reg_tx_cache[i] = tegra20_spdif_read(spdif, reg);
277 }
278
279 clk_disable(spdif->clk_spdif_out);
280
281#endif
282
283 return 0;
284}
285
286#ifdef CONFIG_PM
287int tegra20_spdif_resume(struct snd_soc_dai *cpu_dai)
288{
289 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(cpu_dai);
290 int i, reg;
291
292 clk_enable(spdif->clk_spdif_out);
293
294 /*restore the spdif regs*/
295 for (i = 0; i < TEGRA20_SPDIF_CTRL_CACHE_SIZE; i++)
296 tegra20_spdif_write(spdif, i << 2, spdif->reg_ctrl_cache[i]);
297
298 for (i = 0; i < TEGRA20_SPDIF_TX_CACHE_SIZE; i++) {
299 reg = (TEGRA20_SPDIF_CH_STA_TX_A) + (i << 2);
300 tegra20_spdif_write(spdif, reg, spdif->reg_tx_cache[i]);
301 }
302
303 clk_disable(spdif->clk_spdif_out);
304
305 return 0;
306}
307#else
308#define tegra20_spdif_resume NULL
309#endif
310
311static struct snd_soc_dai_ops tegra20_spdif_dai_ops = {
312 .hw_params = tegra20_spdif_hw_params,
313 .trigger = tegra20_spdif_trigger,
314};
315
316struct snd_soc_dai_driver tegra20_spdif_dai = {
317 .name = DRV_NAME,
318 .probe = tegra20_spdif_probe,
319 .resume = tegra20_spdif_resume,
320 .playback = {
321 .channels_min = 2,
322 .channels_max = 2,
323 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
324 SNDRV_PCM_RATE_48000,
325 .formats = SNDRV_PCM_FMTBIT_S16_LE,
326 },
327 .ops = &tegra20_spdif_dai_ops,
328};
329
330static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
331{
332 struct tegra20_spdif *spdif;
333 struct resource *mem, *memregion, *dmareq;
334 int ret;
335 u32 reg_val;
336
337 spdif = kzalloc(sizeof(struct tegra20_spdif), GFP_KERNEL);
338 if (!spdif) {
339 dev_err(&pdev->dev, "Can't allocate tegra20_spdif\n");
340 ret = -ENOMEM;
341 goto exit;
342 }
343 dev_set_drvdata(&pdev->dev, spdif);
344
345 spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
346 if (IS_ERR(spdif->clk_spdif_out)) {
347 pr_err("Can't retrieve spdif clock\n");
348 ret = PTR_ERR(spdif->clk_spdif_out);
349 goto err_free;
350 }
351
352 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
353 if (!mem) {
354 dev_err(&pdev->dev, "No memory resource\n");
355 ret = -ENODEV;
356 goto err_clk_put;
357 }
358
359 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
360 if (!dmareq) {
361 dev_err(&pdev->dev, "No DMA resource\n");
362 ret = -ENODEV;
363 goto err_clk_put;
364 }
365
366 memregion = request_mem_region(mem->start, resource_size(mem),
367 DRV_NAME);
368 if (!memregion) {
369 dev_err(&pdev->dev, "Memory region already claimed\n");
370 ret = -EBUSY;
371 goto err_clk_put;
372 }
373
374 spdif->regs = ioremap(mem->start, resource_size(mem));
375 if (!spdif->regs) {
376 dev_err(&pdev->dev, "ioremap failed\n");
377 ret = -ENOMEM;
378 goto err_release;
379 }
380
381 spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
382 spdif->playback_dma_data.wrap = 4;
383 spdif->playback_dma_data.width = 32;
384 spdif->playback_dma_data.req_sel = dmareq->start;
385
386 clk_enable(spdif->clk_spdif_out);
387
388 reg_val = tegra20_spdif_read(spdif, TEGRA20_SPDIF_DATA_FIFO_CSR);
389 reg_val &= ~TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK;
390 reg_val |= TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL;
391 tegra20_spdif_write(spdif, TEGRA20_SPDIF_DATA_FIFO_CSR, reg_val);
392
393 clk_disable(spdif->clk_spdif_out);
394
395 ret = snd_soc_register_dai(&pdev->dev, &tegra20_spdif_dai);
396 if (ret) {
397 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
398 ret = -ENOMEM;
399 goto err_unmap;
400 }
401
402 tegra20_spdif_debug_add(spdif);
403
404 return 0;
405
406err_unmap:
407 iounmap(spdif->regs);
408err_release:
409 release_mem_region(mem->start, resource_size(mem));
410err_clk_put:
411 clk_put(spdif->clk_spdif_out);
412err_free:
413 kfree(spdif);
414exit:
415 return ret;
416}
417
418static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
419{
420 struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev);
421 struct resource *res;
422
423 snd_soc_unregister_dai(&pdev->dev);
424
425 tegra20_spdif_debug_remove(spdif);
426
427 iounmap(spdif->regs);
428
429 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
430 release_mem_region(res->start, resource_size(res));
431
432 clk_put(spdif->clk_spdif_out);
433
434 kfree(spdif);
435
436 return 0;
437}
438
439static struct platform_driver tegra20_spdif_driver = {
440 .driver = {
441 .name = DRV_NAME,
442 .owner = THIS_MODULE,
443 },
444 .probe = tegra20_spdif_platform_probe,
445 .remove = __devexit_p(tegra20_spdif_platform_remove),
446};
447
448static int __init snd_tegra20_spdif_init(void)
449{
450 return platform_driver_register(&tegra20_spdif_driver);
451}
452module_init(snd_tegra20_spdif_init);
453
454static void __exit snd_tegra20_spdif_exit(void)
455{
456 platform_driver_unregister(&tegra20_spdif_driver);
457}
458module_exit(snd_tegra20_spdif_exit);
459
460MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
461MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
462MODULE_LICENSE("GPL");
463MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
new file mode 100644
index 00000000000..c1fb6ed2a79
--- /dev/null
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -0,0 +1,556 @@
1/*
2 * tegra20_spdif.h - Definitions for Tegra20 SPDIF driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 * Copyright (c) 2008-2009, NVIDIA Corporation
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#ifndef __TEGRA20_SPDIF_H__
27#define __TEGRA20_SPDIF_H__
28
29#include "tegra_pcm.h"
30
31/* Offsets from TEGRA_SPDIF_BASE */
32
33#define TEGRA20_SPDIF_CTRL 0x0
34#define TEGRA20_SPDIF_STATUS 0x4
35#define TEGRA20_SPDIF_STROBE_CTRL 0x8
36#define TEGRA20_SPDIF_DATA_FIFO_CSR 0x0C
37#define TEGRA20_SPDIF_DATA_OUT 0x40
38#define TEGRA20_SPDIF_DATA_IN 0x80
39#define TEGRA20_SPDIF_CH_STA_RX_A 0x100
40#define TEGRA20_SPDIF_CH_STA_RX_B 0x104
41#define TEGRA20_SPDIF_CH_STA_RX_C 0x108
42#define TEGRA20_SPDIF_CH_STA_RX_D 0x10C
43#define TEGRA20_SPDIF_CH_STA_RX_E 0x110
44#define TEGRA20_SPDIF_CH_STA_RX_F 0x114
45#define TEGRA20_SPDIF_CH_STA_TX_A 0x140
46#define TEGRA20_SPDIF_CH_STA_TX_B 0x144
47#define TEGRA20_SPDIF_CH_STA_TX_C 0x148
48#define TEGRA20_SPDIF_CH_STA_TX_D 0x14C
49#define TEGRA20_SPDIF_CH_STA_TX_E 0x150
50#define TEGRA20_SPDIF_CH_STA_TX_F 0x154
51#define TEGRA20_SPDIF_USR_STA_RX_A 0x180
52#define TEGRA20_SPDIF_USR_DAT_TX_A 0x1C0
53
54/* Fields in TEGRA20_SPDIF_CTRL */
55
56/* Start capturing from 0=right, 1=left channel */
57#define TEGRA20_SPDIF_CTRL_CAP_LC (1 << 30)
58
59/* SPDIF receiver(RX) enable */
60#define TEGRA20_SPDIF_CTRL_RX_EN (1 << 29)
61
62/* SPDIF Transmitter(TX) enable */
63#define TEGRA20_SPDIF_CTRL_TX_EN (1 << 28)
64
65/* Transmit Channel status */
66#define TEGRA20_SPDIF_CTRL_TC_EN (1 << 27)
67
68/* Transmit user Data */
69#define TEGRA20_SPDIF_CTRL_TU_EN (1 << 26)
70
71/* Interrupt on transmit error */
72#define TEGRA20_SPDIF_CTRL_IE_TXE (1 << 25)
73
74/* Interrupt on receive error */
75#define TEGRA20_SPDIF_CTRL_IE_RXE (1 << 24)
76
77/* Interrupt on invalid preamble */
78#define TEGRA20_SPDIF_CTRL_IE_P (1 << 23)
79
80/* Interrupt on "B" preamble */
81#define TEGRA20_SPDIF_CTRL_IE_B (1 << 22)
82
83/* Interrupt when block of channel status received */
84#define TEGRA20_SPDIF_CTRL_IE_C (1 << 21)
85
86/* Interrupt when a valid information unit (IU) is received */
87#define TEGRA20_SPDIF_CTRL_IE_U (1 << 20)
88
89/* Interrupt when RX user FIFO attention level is reached */
90#define TEGRA20_SPDIF_CTRL_QE_RU (1 << 19)
91
92/* Interrupt when TX user FIFO attention level is reached */
93#define TEGRA20_SPDIF_CTRL_QE_TU (1 << 18)
94
95/* Interrupt when RX data FIFO attention level is reached */
96#define TEGRA20_SPDIF_CTRL_QE_RX (1 << 17)
97
98/* Interrupt when TX data FIFO attention level is reached */
99#define TEGRA20_SPDIF_CTRL_QE_TX (1 << 16)
100
101/* Loopback test mode enable */
102#define TEGRA20_SPDIF_CTRL_LBK_EN (1 << 15)
103
104/*
105 * Pack data mode:
106 * 0 = Single data (16 bit needs to be padded to match the
107 * interface data bit size).
108 * 1 = Packeted left/right channel data into a single word.
109 */
110#define TEGRA20_SPDIF_CTRL_PACK (1 << 14)
111
112/*
113 * 00 = 16bit data
114 * 01 = 20bit data
115 * 10 = 24bit data
116 * 11 = raw data
117 */
118#define TEGRA20_SPDIF_BIT_MODE_16BIT 0
119#define TEGRA20_SPDIF_BIT_MODE_20BIT 1
120#define TEGRA20_SPDIF_BIT_MODE_24BIT 2
121#define TEGRA20_SPDIF_BIT_MODE_RAW 3
122
123#define TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT 12
124#define TEGRA20_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
125#define TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA20_SPDIF_BIT_MODE_16BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
126#define TEGRA20_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA20_SPDIF_BIT_MODE_20BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
127#define TEGRA20_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA20_SPDIF_BIT_MODE_24BIT << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
128#define TEGRA20_SPDIF_CTRL_BIT_MODE_RAW (TEGRA20_SPDIF_BIT_MODE_RAW << TEGRA20_SPDIF_CTRL_BIT_MODE_SHIFT)
129
130/* Fields in TEGRA20_SPDIF_STATUS */
131
132/*
133 * Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must
134 * write a 1 to the corresponding bit location to clear the status.
135 */
136
137/*
138 * Receiver(RX) shifter is busy receiving data.
139 * This bit is asserted when the receiver first locked onto the
140 * preamble of the data stream after RX_EN is asserted. This bit is
141 * deasserted when either,
142 * (a) the end of a frame is reached after RX_EN is deeasserted, or
143 * (b) the SPDIF data stream becomes inactive.
144 */
145#define TEGRA20_SPDIF_STATUS_RX_BSY (1 << 29)
146
147/*
148 * Transmitter(TX) shifter is busy transmitting data.
149 * This bit is asserted when TX_EN is asserted.
150 * This bit is deasserted when the end of a frame is reached after
151 * TX_EN is deasserted.
152 */
153#define TEGRA20_SPDIF_STATUS_TX_BSY (1 << 28)
154
155/*
156 * TX is busy shifting out channel status.
157 * This bit is asserted when both TX_EN and TC_EN are asserted and
158 * data from CH_STA_TX_A register is loaded into the internal shifter.
159 * This bit is deasserted when either,
160 * (a) the end of a frame is reached after TX_EN is deasserted, or
161 * (b) CH_STA_TX_F register is loaded into the internal shifter.
162 */
163#define TEGRA20_SPDIF_STATUS_TC_BSY (1 << 27)
164
165/*
166 * TX User data FIFO busy.
167 * This bit is asserted when TX_EN and TXU_EN are asserted and
168 * there's data in the TX user FIFO. This bit is deassert when either,
169 * (a) the end of a frame is reached after TX_EN is deasserted, or
170 * (b) there's no data left in the TX user FIFO.
171 */
172#define TEGRA20_SPDIF_STATUS_TU_BSY (1 << 26)
173
174/* TX FIFO Underrun error status */
175#define TEGRA20_SPDIF_STATUS_TX_ERR (1 << 25)
176
177/* RX FIFO Overrun error status */
178#define TEGRA20_SPDIF_STATUS_RX_ERR (1 << 24)
179
180/* Preamble status: 0=Preamble OK, 1=bad/missing preamble */
181#define TEGRA20_SPDIF_STATUS_IS_P (1 << 23)
182
183/* B-preamble detection status: 0=not detected, 1=B-preamble detected */
184#define TEGRA20_SPDIF_STATUS_IS_B (1 << 22)
185
186/*
187 * RX channel block data receive status:
188 * 0=entire block not recieved yet.
189 * 1=received entire block of channel status,
190 */
191#define TEGRA20_SPDIF_STATUS_IS_C (1 << 21)
192
193/* RX User Data Valid flag: 1=valid IU detected, 0 = no IU detected. */
194#define TEGRA20_SPDIF_STATUS_IS_U (1 << 20)
195
196/*
197 * RX User FIFO Status:
198 * 1=attention level reached, 0=attention level not reached.
199 */
200#define TEGRA20_SPDIF_STATUS_QS_RU (1 << 19)
201
202/*
203 * TX User FIFO Status:
204 * 1=attention level reached, 0=attention level not reached.
205 */
206#define TEGRA20_SPDIF_STATUS_QS_TU (1 << 18)
207
208/*
209 * RX Data FIFO Status:
210 * 1=attention level reached, 0=attention level not reached.
211 */
212#define TEGRA20_SPDIF_STATUS_QS_RX (1 << 17)
213
214/*
215 * TX Data FIFO Status:
216 * 1=attention level reached, 0=attention level not reached.
217 */
218#define TEGRA20_SPDIF_STATUS_QS_TX (1 << 16)
219
220/* Fields in TEGRA20_SPDIF_STROBE_CTRL */
221
222/*
223 * Indicates the approximate number of detected SPDIFIN clocks within a
224 * bi-phase period.
225 */
226#define TEGRA20_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16
227#define TEGRA20_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA20_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
228
229/* Data strobe mode: 0=Auto-locked 1=Manual locked */
230#define TEGRA20_SPDIF_STROBE_CTRL_STROBE (1 << 15)
231
232/*
233 * Manual data strobe time within the bi-phase clock period (in terms of
234 * the number of over-sampling clocks).
235 */
236#define TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8
237#define TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA20_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
238
239/*
240 * Manual SPDIFIN bi-phase clock period (in terms of the number of
241 * over-sampling clocks).
242 */
243#define TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0
244#define TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA20_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
245
246/* Fields in SPDIF_DATA_FIFO_CSR */
247
248/* Clear Receiver User FIFO (RX USR.FIFO) */
249#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_CLR (1 << 31)
250
251#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT 0
252#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS 1
253#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS 2
254#define TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS 3
255
256/* RU FIFO attention level */
257#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT 29
258#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK \
259 (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
260#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL \
261 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
262#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL \
263 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
264#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL \
265 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
266#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL \
267 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
268
269/* Number of RX USR.FIFO levels with valid data. */
270#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT 24
271#define TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK (0x1f << TEGRA20_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT)
272
273/* Clear Transmitter User FIFO (TX USR.FIFO) */
274#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_CLR (1 << 23)
275
276/* TU FIFO attention level */
277#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT 21
278#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK \
279 (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
280#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL \
281 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
282#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL \
283 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
284#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL \
285 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
286#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL \
287 (TEGRA20_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
288
289/* Number of TX USR.FIFO levels that could be filled. */
290#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT 16
291#define TEGRA20_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT)
292
293/* Clear Receiver Data FIFO (RX DATA.FIFO) */
294#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_CLR (1 << 15)
295
296#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT 0
297#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS 1
298#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS 2
299#define TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOT 3
300
301/* RU FIFO attention level */
302#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT 13
303#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK \
304 (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
305#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL \
306 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
307#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL \
308 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
309#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL \
310 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
311#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL \
312 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
313
314/* Number of RX DATA.FIFO levels with valid data. */
315#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT 8
316#define TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK (0x1f << TEGRA20_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT)
317
318/* Clear Transmitter Data FIFO (TX DATA.FIFO) */
319#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_CLR (1 << 7)
320
321/* TU FIFO attention level */
322#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT 5
323#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK \
324 (0x3 << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
325#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL \
326 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
327#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL \
328 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
329#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL \
330 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
331#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL \
332 (TEGRA20_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
333
334/* Number of TX DATA.FIFO levels that could be filled. */
335#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT 0
336#define TEGRA20_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT)
337
338/* Fields in TEGRA20_SPDIF_DATA_OUT */
339
340/*
341 * This register has 5 different formats:
342 * 16-bit (BIT_MODE=00, PACK=0)
343 * 20-bit (BIT_MODE=01, PACK=0)
344 * 24-bit (BIT_MODE=10, PACK=0)
345 * raw (BIT_MODE=11, PACK=0)
346 * 16-bit packed (BIT_MODE=00, PACK=1)
347 */
348
349#define TEGRA20_SPDIF_DATA_OUT_DATA_16_SHIFT 0
350#define TEGRA20_SPDIF_DATA_OUT_DATA_16_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_SHIFT)
351
352#define TEGRA20_SPDIF_DATA_OUT_DATA_20_SHIFT 0
353#define TEGRA20_SPDIF_DATA_OUT_DATA_20_MASK (0xfffff << TEGRA20_SPDIF_DATA_OUT_DATA_20_SHIFT)
354
355#define TEGRA20_SPDIF_DATA_OUT_DATA_24_SHIFT 0
356#define TEGRA20_SPDIF_DATA_OUT_DATA_24_MASK (0xffffff << TEGRA20_SPDIF_DATA_OUT_DATA_24_SHIFT)
357
358#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_P (1 << 31)
359#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_C (1 << 30)
360#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_U (1 << 29)
361#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_V (1 << 28)
362
363#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT 8
364#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK (0xfffff << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT)
365
366#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT 4
367#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK (0xf << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT)
368
369#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT 0
370#define TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT)
371
372#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT 16
373#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT)
374
375#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT 0
376#define TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA20_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT)
377
378/* Fields in TEGRA20_SPDIF_DATA_IN */
379
380/*
381 * This register has 5 different formats:
382 * 16-bit (BIT_MODE=00, PACK=0)
383 * 20-bit (BIT_MODE=01, PACK=0)
384 * 24-bit (BIT_MODE=10, PACK=0)
385 * raw (BIT_MODE=11, PACK=0)
386 * 16-bit packed (BIT_MODE=00, PACK=1)
387 *
388 * Bits 31:24 are common to all modes except 16-bit packed
389 */
390
391#define TEGRA20_SPDIF_DATA_IN_DATA_P (1 << 31)
392#define TEGRA20_SPDIF_DATA_IN_DATA_C (1 << 30)
393#define TEGRA20_SPDIF_DATA_IN_DATA_U (1 << 29)
394#define TEGRA20_SPDIF_DATA_IN_DATA_V (1 << 28)
395
396#define TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT 24
397#define TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT)
398
399#define TEGRA20_SPDIF_DATA_IN_DATA_16_SHIFT 0
400#define TEGRA20_SPDIF_DATA_IN_DATA_16_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_SHIFT)
401
402#define TEGRA20_SPDIF_DATA_IN_DATA_20_SHIFT 0
403#define TEGRA20_SPDIF_DATA_IN_DATA_20_MASK (0xfffff << TEGRA20_SPDIF_DATA_IN_DATA_20_SHIFT)
404
405#define TEGRA20_SPDIF_DATA_IN_DATA_24_SHIFT 0
406#define TEGRA20_SPDIF_DATA_IN_DATA_24_MASK (0xffffff << TEGRA20_SPDIF_DATA_IN_DATA_24_SHIFT)
407
408#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT 8
409#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_MASK (0xfffff << TEGRA20_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT)
410
411#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT 4
412#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT)
413
414#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT 0
415#define TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA20_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT)
416
417#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT 16
418#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT)
419
420#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT 0
421#define TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA20_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT)
422
423/* Fields in TEGRA20_SPDIF_CH_STA_RX_A */
424/* Fields in TEGRA20_SPDIF_CH_STA_RX_B */
425/* Fields in TEGRA20_SPDIF_CH_STA_RX_C */
426/* Fields in TEGRA20_SPDIF_CH_STA_RX_D */
427/* Fields in TEGRA20_SPDIF_CH_STA_RX_E */
428/* Fields in TEGRA20_SPDIF_CH_STA_RX_F */
429
430/*
431 * The 6-word receive channel data page buffer holds a block (192 frames) of
432 * channel status information. The order of receive is from LSB to MSB
433 * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
434 */
435
436/* Fields in TEGRA20_SPDIF_CH_STA_TX_A */
437#define TEGRA20_SPDIF_CH_STA_TX_A_SF_22050 0x4
438#define TEGRA20_SPDIF_CH_STA_TX_A_SF_24000 0x6
439#define TEGRA20_SPDIF_CH_STA_TX_A_SF_32000 0x3
440#define TEGRA20_SPDIF_CH_STA_TX_A_SF_44100 0x0
441#define TEGRA20_SPDIF_CH_STA_TX_A_SF_48000 0x2
442#define TEGRA20_SPDIF_CH_STA_TX_A_SF_88200 0x8
443#define TEGRA20_SPDIF_CH_STA_TX_A_SF_96000 0xA
444#define TEGRA20_SPDIF_CH_STA_TX_A_SF_176400 0xC
445#define TEGRA20_SPDIF_CH_STA_TX_A_SF_192000 0xE
446
447#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT 24
448#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK \
449 (0xF << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
450#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_22050 \
451 (TEGRA20_SPDIF_CH_STA_TX_A_SF_22050 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
452#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_24000 \
453 (TEGRA20_SPDIF_CH_STA_TX_A_SF_24000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
454#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000 \
455 (TEGRA20_SPDIF_CH_STA_TX_A_SF_32000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
456#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100 \
457 (TEGRA20_SPDIF_CH_STA_TX_A_SF_44100 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
458#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000 \
459 (TEGRA20_SPDIF_CH_STA_TX_A_SF_48000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
460#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200 \
461 (TEGRA20_SPDIF_CH_STA_TX_A_SF_88200 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
462#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000 \
463 (TEGRA20_SPDIF_CH_STA_TX_A_SF_96000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
464#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400 \
465 (TEGRA20_SPDIF_CH_STA_TX_A_SF_176400 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
466#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000 \
467 (TEGRA20_SPDIF_CH_STA_TX_A_SF_192000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
468
469/* Fields in TEGRA20_SPDIF_CH_STA_TX_B */
470#define TEGRA20_SPDIF_CH_STA_TX_B_SF_8000 0x6
471#define TEGRA20_SPDIF_CH_STA_TX_B_SF_11025 0xA
472#define TEGRA20_SPDIF_CH_STA_TX_B_SF_12000 0x2
473#define TEGRA20_SPDIF_CH_STA_TX_B_SF_16000 0x8
474#define TEGRA20_SPDIF_CH_STA_TX_B_SF_22050 0xB
475#define TEGRA20_SPDIF_CH_STA_TX_B_SF_24000 0x9
476#define TEGRA20_SPDIF_CH_STA_TX_B_SF_32000 0xC
477#define TEGRA20_SPDIF_CH_STA_TX_B_SF_44100 0xF
478#define TEGRA20_SPDIF_CH_STA_TX_B_SF_48000 0xD
479#define TEGRA20_SPDIF_CH_STA_TX_B_SF_88200 0x7
480#define TEGRA20_SPDIF_CH_STA_TX_B_SF_96000 0x5
481#define TEGRA20_SPDIF_CH_STA_TX_B_SF_176400 0x3
482#define TEGRA20_SPDIF_CH_STA_TX_B_SF_192000 0x1
483
484#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT 4
485#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK \
486 (0xF << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
487#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_8000 \
488 (TEGRA20_SPDIF_CH_STA_TX_B_SF_8000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
489#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_11025 \
490 (TEGRA20_SPDIF_CH_STA_TX_B_SF_11025 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
491#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_12000 \
492 (TEGRA20_SPDIF_CH_STA_TX_B_SF_12000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
493#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_16000 \
494 (TEGRA20_SPDIF_CH_STA_TX_B_SF_16000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
495#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_22050 \
496 (TEGRA20_SPDIF_CH_STA_TX_B_SF_22025 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
497#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_24000 \
498 (TEGRA20_SPDIF_CH_STA_TX_B_SF_24000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
499#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000 \
500 (TEGRA20_SPDIF_CH_STA_TX_B_SF_32000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
501#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100 \
502 (TEGRA20_SPDIF_CH_STA_TX_B_SF_44100 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
503#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000 \
504 (TEGRA20_SPDIF_CH_STA_TX_B_SF_48000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
505#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200 \
506 (TEGRA20_SPDIF_CH_STA_TX_B_SF_88200 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
507#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000 \
508 (TEGRA20_SPDIF_CH_STA_TX_B_SF_96000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
509#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400 \
510 (TEGRA20_SPDIF_CH_STA_TX_B_SF_176400 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
511#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000 \
512 (TEGRA20_SPDIF_CH_STA_TX_B_SF_192000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
513
514/* Fields in TEGRA20_SPDIF_CH_STA_TX_C */
515/* Fields in TEGRA20_SPDIF_CH_STA_TX_D */
516/* Fields in TEGRA20_SPDIF_CH_STA_TX_E */
517/* Fields in TEGRA20_SPDIF_CH_STA_TX_F */
518
519/*
520 * The 6-word transmit channel data page buffer holds a block (192 frames) of
521 * channel status information. The order of transmission is from LSB to MSB
522 * bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A.
523 */
524
525/* Fields in TEGRA20_SPDIF_USR_STA_RX_A */
526
527/*
528 * This 4-word deep FIFO receives user FIFO field information. The order of
529 * receive is from LSB to MSB bit.
530 */
531
532/* Fields in TEGRA20_SPDIF_USR_DAT_TX_A */
533
534/*
535 * This 4-word deep FIFO transmits user FIFO field information. The order of
536 * transmission is from LSB to MSB bit.
537 */
538#ifdef CONFIG_PM
539#define TEGRA20_SPDIF_CTRL_CACHE_SIZE ((TEGRA20_SPDIF_DATA_FIFO_CSR >> 2) + 1)
540#define TEGRA20_SPDIF_TX_CACHE_SIZE (((TEGRA20_SPDIF_CH_STA_TX_F - TEGRA20_SPDIF_CH_STA_TX_A) >> 2) + 1)
541#endif
542
543struct tegra20_spdif {
544 struct clk *clk_spdif_out;
545 struct tegra_pcm_dma_params capture_dma_data;
546 struct tegra_pcm_dma_params playback_dma_data;
547 void __iomem *regs;
548 struct dentry *debug;
549 u32 reg_ctrl;
550#ifdef CONFIG_PM
551 u32 reg_ctrl_cache[TEGRA20_SPDIF_CTRL_CACHE_SIZE];
552 u32 reg_tx_cache[TEGRA20_SPDIF_TX_CACHE_SIZE];
553#endif
554};
555
556#endif
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
new file mode 100644
index 00000000000..710d9465b4b
--- /dev/null
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -0,0 +1,665 @@
1/*
2 * tegra30_ahub.c - Tegra 30 AHUB driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, 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/clk.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/device.h>
27#include <linux/platform_device.h>
28#include <linux/seq_file.h>
29#include <linux/slab.h>
30#include <linux/io.h>
31#include <mach/dma.h>
32#include <mach/iomap.h>
33#include <sound/soc.h>
34#include "tegra30_ahub.h"
35
36#define DRV_NAME "tegra30-ahub"
37
38static struct tegra30_ahub *ahub;
39
40static inline void tegra30_apbif_write(u32 reg, u32 val)
41{
42#ifdef CONFIG_PM
43 ahub->apbif_reg_cache[reg >> 2] = val;
44#endif
45 __raw_writel(val, ahub->apbif_regs + reg);
46}
47
48static inline u32 tegra30_apbif_read(u32 reg)
49{
50 return __raw_readl(ahub->apbif_regs + reg);
51}
52
53static inline void tegra30_audio_write(u32 reg, u32 val)
54{
55#ifdef CONFIG_PM
56 ahub->ahub_reg_cache[reg >> 2] = val;
57#endif
58 __raw_writel(val, ahub->audio_regs + reg);
59}
60
61static inline u32 tegra30_audio_read(u32 reg)
62{
63 return __raw_readl(ahub->audio_regs + reg);
64}
65
66#ifdef CONFIG_PM
67int tegra30_ahub_apbif_resume()
68{
69 int i = 0;
70 int cache_idx_rsvd;
71
72 tegra30_ahub_enable_clocks();
73
74 /*restore ahub regs*/
75 for (i = 0; i < TEGRA30_AHUB_AUDIO_RX_COUNT; i++)
76 tegra30_audio_write(i<<2, ahub->ahub_reg_cache[i]);
77
78 /*restore apbif regs*/
79 cache_idx_rsvd = TEGRA30_APBIF_CACHE_REG_INDEX_RSVD;
80 for (i = 0; i < TEGRA30_APBIF_CACHE_REG_COUNT; i++) {
81 if (i == cache_idx_rsvd) {
82 cache_idx_rsvd +=
83 TEGRA30_APBIF_CACHE_REG_INDEX_RSVD_STRIDE;
84 continue;
85 }
86
87 tegra30_apbif_write(i<<2, ahub->apbif_reg_cache[i]);
88 }
89
90 tegra30_ahub_disable_clocks();
91
92 return 0;
93}
94#endif
95
96/*
97 * clk_apbif isn't required for a theoretical I2S<->I2S configuration where
98 * no PCM data is read from or sent to memory. However, that's an unlikely
99 * use-case, and not something the rest of the driver supports right now, so
100 * we'll just treat the two clocks as one for now.
101 *
102 * This function should not be a plain ref-count. Instead, each active stream
103 * contributes some requirement to the minimum clock rate, so starting or
104 * stopping streams should dynamically adjust the clock as required. However,
105 * this is not yet implemented.
106 */
107void tegra30_ahub_enable_clocks(void)
108{
109 clk_enable(ahub->clk_d_audio);
110 clk_enable(ahub->clk_apbif);
111}
112
113void tegra30_ahub_disable_clocks(void)
114{
115 clk_disable(ahub->clk_apbif);
116 clk_disable(ahub->clk_d_audio);
117}
118
119#ifdef CONFIG_DEBUG_FS
120static inline u32 tegra30_ahub_read(u32 space, u32 reg)
121{
122 if (space == 0)
123 return tegra30_apbif_read(reg);
124 else
125 return tegra30_audio_read(reg);
126}
127
128static int tegra30_ahub_show(struct seq_file *s, void *unused)
129{
130#define REG(space, r) { space, r, 0, 1, #r }
131#define ARR(space, r) { space, r, r##_STRIDE, r##_COUNT, #r }
132 static const struct {
133 int space;
134 u32 offset;
135 u32 stride;
136 u32 count;
137 const char *name;
138 } regs[] = {
139 ARR(0, TEGRA30_AHUB_CHANNEL_CTRL),
140 ARR(0, TEGRA30_AHUB_CHANNEL_CLEAR),
141 ARR(0, TEGRA30_AHUB_CHANNEL_STATUS),
142 ARR(0, TEGRA30_AHUB_CIF_TX_CTRL),
143 ARR(0, TEGRA30_AHUB_CIF_RX_CTRL),
144 REG(0, TEGRA30_AHUB_CONFIG_LINK_CTRL),
145 REG(0, TEGRA30_AHUB_MISC_CTRL),
146 REG(0, TEGRA30_AHUB_APBDMA_LIVE_STATUS),
147 REG(0, TEGRA30_AHUB_I2S_LIVE_STATUS),
148 ARR(0, TEGRA30_AHUB_DAM_LIVE_STATUS),
149 REG(0, TEGRA30_AHUB_SPDIF_LIVE_STATUS),
150 REG(0, TEGRA30_AHUB_I2S_INT_MASK),
151 REG(0, TEGRA30_AHUB_DAM_INT_MASK),
152 REG(0, TEGRA30_AHUB_SPDIF_INT_MASK),
153 REG(0, TEGRA30_AHUB_APBIF_INT_MASK),
154 REG(0, TEGRA30_AHUB_I2S_INT_STATUS),
155 REG(0, TEGRA30_AHUB_DAM_INT_STATUS),
156 REG(0, TEGRA30_AHUB_SPDIF_INT_STATUS),
157 REG(0, TEGRA30_AHUB_APBIF_INT_STATUS),
158 REG(0, TEGRA30_AHUB_I2S_INT_SOURCE),
159 REG(0, TEGRA30_AHUB_DAM_INT_SOURCE),
160 REG(0, TEGRA30_AHUB_SPDIF_INT_SOURCE),
161 REG(0, TEGRA30_AHUB_APBIF_INT_SOURCE),
162 REG(0, TEGRA30_AHUB_I2S_INT_SET),
163 REG(0, TEGRA30_AHUB_DAM_INT_SET),
164 REG(0, TEGRA30_AHUB_SPDIF_INT_SET),
165 REG(0, TEGRA30_AHUB_APBIF_INT_SET),
166 ARR(1, TEGRA30_AHUB_AUDIO_RX),
167 };
168#undef ARRG
169#undef REG
170
171 int i, j;
172
173 tegra30_ahub_enable_clocks();
174
175 for (i = 0; i < ARRAY_SIZE(regs); i++) {
176 if (regs[i].count > 1) {
177 for (j = 0; j < regs[i].count; j++) {
178 u32 reg = regs[i].offset + (j * regs[i].stride);
179 u32 val = tegra30_ahub_read(regs[i].space, reg);
180 seq_printf(s, "%s[%d] = %08x\n", regs[i].name,
181 j, val);
182 }
183 } else {
184 u32 val = tegra30_ahub_read(regs[i].space,
185 regs[i].offset);
186 seq_printf(s, "%s = %08x\n", regs[i].name, val);
187 }
188 }
189
190 tegra30_ahub_disable_clocks();
191
192 return 0;
193}
194
195static int tegra30_ahub_debug_open(struct inode *inode, struct file *file)
196{
197 return single_open(file, tegra30_ahub_show, inode->i_private);
198}
199
200static const struct file_operations tegra30_ahub_debug_fops = {
201 .open = tegra30_ahub_debug_open,
202 .read = seq_read,
203 .llseek = seq_lseek,
204 .release = single_release,
205};
206
207static void tegra30_ahub_debug_add(struct tegra30_ahub *ahub)
208{
209 ahub->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
210 snd_soc_debugfs_root, ahub,
211 &tegra30_ahub_debug_fops);
212}
213
214static void tegra30_ahub_debug_remove(struct tegra30_ahub *ahub)
215{
216 if (ahub->debug)
217 debugfs_remove(ahub->debug);
218}
219#else
220static inline void tegra30_ahub_debug_add(struct tegra30_ahub *ahub)
221{
222}
223
224static inline void tegra30_ahub_debug_remove(struct tegra30_ahub *ahub)
225{
226}
227#endif
228
229int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
230 unsigned long *fiforeg,
231 unsigned long *reqsel)
232{
233 int channel;
234 u32 reg, val;
235
236 channel = find_first_zero_bit(ahub->rx_usage,
237 TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
238 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
239 return -EBUSY;
240
241 __set_bit(channel, ahub->rx_usage);
242
243 *rxcif = TEGRA30_AHUB_RXCIF_APBIF_RX0 + channel;
244 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_RXFIFO +
245 (channel * TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE);
246 *reqsel = TEGRA_DMA_REQ_SEL_APBIF_CH0 + channel;
247
248 tegra30_ahub_enable_clocks();
249
250 reg = TEGRA30_AHUB_CHANNEL_CTRL +
251 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
252 val = tegra30_apbif_read(reg);
253 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK |
254 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK);
255 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT) |
256 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN |
257 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
258 tegra30_apbif_write(reg, val);
259
260 reg = TEGRA30_AHUB_CIF_RX_CTRL +
261 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
262 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
263 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
264 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
265 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
266 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
267 TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
268 tegra30_apbif_write(reg, val);
269
270 tegra30_ahub_disable_clocks();
271
272 return 0;
273}
274
275int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
276{
277 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
278 int reg, val;
279
280 tegra30_ahub_enable_clocks();
281
282 reg = TEGRA30_AHUB_CHANNEL_CTRL +
283 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
284 val = tegra30_apbif_read(reg);
285 val |= TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
286 tegra30_apbif_write(reg, val);
287
288 return 0;
289}
290
291int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
292{
293 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
294 int reg, val;
295
296 reg = TEGRA30_AHUB_CHANNEL_CTRL +
297 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
298 val = tegra30_apbif_read(reg);
299 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
300 tegra30_apbif_write(reg, val);
301
302 tegra30_ahub_disable_clocks();
303
304 return 0;
305}
306
307int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
308{
309 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
310
311 __clear_bit(channel, ahub->rx_usage);
312
313 return 0;
314}
315
316int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
317 unsigned long *fiforeg,
318 unsigned long *reqsel)
319{
320 int channel;
321 u32 reg, val;
322
323 channel = find_first_zero_bit(ahub->tx_usage,
324 TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
325 if (channel >= TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
326 return -EBUSY;
327
328 __set_bit(channel, ahub->tx_usage);
329
330 *txcif = TEGRA30_AHUB_TXCIF_APBIF_TX0 + channel;
331 *fiforeg = ahub->apbif_addr + TEGRA30_AHUB_CHANNEL_TXFIFO +
332 (channel * TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE);
333 *reqsel = TEGRA_DMA_REQ_SEL_APBIF_CH0 + channel;
334
335 tegra30_ahub_enable_clocks();
336
337 reg = TEGRA30_AHUB_CHANNEL_CTRL +
338 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
339 val = tegra30_apbif_read(reg);
340 val &= ~(TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK |
341 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK);
342 val |= (7 << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT) |
343 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN |
344 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
345 tegra30_apbif_write(reg, val);
346
347 reg = TEGRA30_AHUB_CIF_TX_CTRL +
348 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
349 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
350 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
351 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
352 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
353 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
354 TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
355 tegra30_apbif_write(reg, val);
356
357 tegra30_ahub_disable_clocks();
358
359 return 0;
360}
361
362int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif)
363{
364 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
365 int reg, val;
366
367 tegra30_ahub_enable_clocks();
368
369 reg = TEGRA30_AHUB_CHANNEL_CTRL +
370 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
371 val = tegra30_apbif_read(reg);
372 val |= TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
373 tegra30_apbif_write(reg, val);
374
375 return 0;
376}
377
378int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif)
379{
380 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
381 int reg, val;
382
383 reg = TEGRA30_AHUB_CHANNEL_CTRL +
384 (channel * TEGRA30_AHUB_CHANNEL_CTRL_STRIDE);
385 val = tegra30_apbif_read(reg);
386 val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
387 tegra30_apbif_write(reg, val);
388
389 tegra30_ahub_disable_clocks();
390
391 return 0;
392}
393
394int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif)
395{
396 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
397
398 __clear_bit(channel, ahub->tx_usage);
399
400 return 0;
401}
402
403int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
404 enum tegra30_ahub_txcif txcif)
405{
406 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
407 int reg;
408
409 tegra30_ahub_enable_clocks();
410
411 reg = TEGRA30_AHUB_AUDIO_RX +
412 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
413 tegra30_audio_write(reg, 1 << txcif);
414
415 tegra30_ahub_disable_clocks();
416
417 return 0;
418}
419
420int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
421{
422 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
423 int reg;
424
425 tegra30_ahub_enable_clocks();
426
427 reg = TEGRA30_AHUB_AUDIO_RX +
428 (channel * TEGRA30_AHUB_AUDIO_RX_STRIDE);
429 tegra30_audio_write(reg, 0);
430
431 tegra30_ahub_disable_clocks();
432
433 return 0;
434}
435
436int tegra30_ahub_set_rx_cif_channels(enum tegra30_ahub_rxcif rxcif,
437 unsigned int audio_ch,
438 unsigned int client_ch)
439{
440 int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
441 unsigned int reg, val;
442
443 tegra30_ahub_enable_clocks();
444
445 reg = TEGRA30_AHUB_CIF_RX_CTRL +
446 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
447 val = tegra30_apbif_read(reg);
448 val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
449 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
450 val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
451 ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
452 tegra30_apbif_write(reg, val);
453
454 tegra30_ahub_disable_clocks();
455
456 return 0;
457}
458
459int tegra30_ahub_set_tx_cif_channels(enum tegra30_ahub_txcif txcif,
460 unsigned int audio_ch,
461 unsigned int client_ch)
462{
463 int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
464 unsigned int reg, val;
465
466 tegra30_ahub_enable_clocks();
467
468 reg = TEGRA30_AHUB_CIF_TX_CTRL +
469 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
470 val = tegra30_apbif_read(reg);
471 val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
472 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
473 val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
474 ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
475
476 tegra30_apbif_write(reg, val);
477
478 tegra30_ahub_disable_clocks();
479
480 return 0;
481}
482
483static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
484{
485 struct resource *res0, *res1, *region;
486 int ret = 0;
487#ifdef CONFIG_PM
488 int i = 0, cache_idx_rsvd;
489#endif
490 int clkm_rate;
491
492 if (ahub)
493 return -ENODEV;
494
495 ahub = kzalloc(sizeof(struct tegra30_ahub), GFP_KERNEL);
496 if (!ahub) {
497 dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n");
498 ret = -ENOMEM;
499 goto exit;
500 }
501 ahub->dev = &pdev->dev;
502
503 ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
504 if (IS_ERR(ahub->clk_d_audio)) {
505 dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
506 ret = PTR_ERR(ahub->clk_d_audio);
507 goto err_free;
508 }
509 clkm_rate = clk_get_rate(clk_get_parent(ahub->clk_d_audio));
510 while (clkm_rate > 12000000)
511 clkm_rate >>= 1;
512
513 clk_set_rate(ahub->clk_d_audio,clkm_rate);
514
515 ahub->clk_apbif = clk_get(&pdev->dev, "apbif");
516 if (IS_ERR(ahub->clk_apbif)) {
517 dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
518 ret = PTR_ERR(ahub->clk_apbif);
519 goto err_clk_put_d_audio;
520 }
521
522 res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
523 if (!res0) {
524 dev_err(&pdev->dev, "No memory 0 resource\n");
525 ret = -ENODEV;
526 goto err_clk_put_apbif;
527 }
528
529 region = request_mem_region(res0->start, resource_size(res0),
530 pdev->name);
531 if (!region) {
532 dev_err(&pdev->dev, "Memory region 0 already claimed\n");
533 ret = -EBUSY;
534 goto err_clk_put_apbif;
535 }
536
537 ahub->apbif_regs = ioremap(res0->start, resource_size(res0));
538 if (!ahub->apbif_regs) {
539 dev_err(&pdev->dev, "ioremap 0 failed\n");
540 ret = -ENOMEM;
541 goto err_release0;
542 }
543
544 ahub->apbif_addr = res0->start;
545
546 res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
547 if (!res1) {
548 dev_err(&pdev->dev, "No memory 1 resource\n");
549 ret = -ENODEV;
550 goto err_unmap0;
551 }
552
553 region = request_mem_region(res1->start, resource_size(res1),
554 pdev->name);
555 if (!region) {
556 dev_err(&pdev->dev, "Memory region 1 already claimed\n");
557 ret = -EBUSY;
558 goto err_unmap0;
559 }
560
561 ahub->audio_regs = ioremap(res1->start, resource_size(res1));
562 if (!ahub->audio_regs) {
563 dev_err(&pdev->dev, "ioremap 1 failed\n");
564 ret = -ENOMEM;
565 goto err_release1;
566 }
567
568#ifdef CONFIG_PM
569 /* cache the POR values of ahub/apbif regs*/
570 tegra30_ahub_enable_clocks();
571
572 for (i = 0; i < TEGRA30_AHUB_AUDIO_RX_COUNT; i++)
573 ahub->ahub_reg_cache[i] = tegra30_audio_read(i<<2);
574
575 cache_idx_rsvd = TEGRA30_APBIF_CACHE_REG_INDEX_RSVD;
576 for (i = 0; i < TEGRA30_APBIF_CACHE_REG_COUNT; i++) {
577 if (i == cache_idx_rsvd) {
578 cache_idx_rsvd +=
579 TEGRA30_APBIF_CACHE_REG_INDEX_RSVD_STRIDE;
580 continue;
581 }
582
583 ahub->apbif_reg_cache[i] = tegra30_apbif_read(i<<2);
584 }
585
586 tegra30_ahub_disable_clocks();
587#endif
588
589 tegra30_ahub_debug_add(ahub);
590
591 platform_set_drvdata(pdev, ahub);
592
593 return 0;
594
595err_release1:
596 release_mem_region(res1->start, resource_size(res1));
597err_unmap0:
598 iounmap(ahub->apbif_regs);
599err_release0:
600 release_mem_region(res0->start, resource_size(res0));
601err_clk_put_apbif:
602 clk_put(ahub->clk_apbif);
603err_clk_put_d_audio:
604 clk_put(ahub->clk_d_audio);
605err_free:
606 kfree(ahub);
607 ahub = 0;
608exit:
609 return ret;
610}
611
612static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
613{
614 struct resource *res;
615
616 if (!ahub)
617 return -ENODEV;
618
619 platform_set_drvdata(pdev, NULL);
620
621 tegra30_ahub_debug_remove(ahub);
622
623 iounmap(ahub->audio_regs);
624
625 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
626 release_mem_region(res->start, resource_size(res));
627
628 iounmap(ahub->apbif_regs);
629
630 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
631 release_mem_region(res->start, resource_size(res));
632
633 clk_put(ahub->clk_apbif);
634 clk_put(ahub->clk_d_audio);
635
636 kfree(ahub);
637 ahub = 0;
638
639 return 0;
640}
641
642static struct platform_driver tegra30_ahub_driver = {
643 .probe = tegra30_ahub_probe,
644 .remove = __devexit_p(tegra30_ahub_remove),
645 .driver = {
646 .name = DRV_NAME,
647 },
648};
649
650static int __init tegra30_ahub_modinit(void)
651{
652 return platform_driver_register(&tegra30_ahub_driver);
653}
654module_init(tegra30_ahub_modinit);
655
656static void __exit tegra30_ahub_modexit(void)
657{
658 platform_driver_unregister(&tegra30_ahub_driver);
659}
660module_exit(tegra30_ahub_modexit);
661
662MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
663MODULE_DESCRIPTION("Tegra 30 AHUB driver");
664MODULE_LICENSE("GPL");
665MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
new file mode 100644
index 00000000000..7de1b7c86c7
--- /dev/null
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -0,0 +1,512 @@
1/*
2 * tegra30_ahub.h - Definitions for Tegra 30 AHUB driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, 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#ifndef __TEGRA30_AHUB_H__
24#define __TEGRA30_AHUB_H__
25
26/* Fields in *_CIF_RX/TX_CTRL; used by AHUB FIFOs, and all other audio modules */
27
28#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 28
29#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf
30#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
31
32/* Channel count minus 1 */
33#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24
34#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7
35#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
36
37/* Channel count minus 1 */
38#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
39#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7
40#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
41
42#define TEGRA30_AUDIOCIF_BITS_4 0
43#define TEGRA30_AUDIOCIF_BITS_8 1
44#define TEGRA30_AUDIOCIF_BITS_12 2
45#define TEGRA30_AUDIOCIF_BITS_16 3
46#define TEGRA30_AUDIOCIF_BITS_20 4
47#define TEGRA30_AUDIOCIF_BITS_24 5
48#define TEGRA30_AUDIOCIF_BITS_28 6
49#define TEGRA30_AUDIOCIF_BITS_32 7
50
51#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT 12
52#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK (7 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
53#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_4 (TEGRA30_AUDIOCIF_BITS_4 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
54#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_8 (TEGRA30_AUDIOCIF_BITS_8 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
55#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_12 (TEGRA30_AUDIOCIF_BITS_12 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
56#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 (TEGRA30_AUDIOCIF_BITS_16 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
57#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_20 (TEGRA30_AUDIOCIF_BITS_20 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
58#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_24 (TEGRA30_AUDIOCIF_BITS_24 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
59#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_28 (TEGRA30_AUDIOCIF_BITS_28 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
60#define TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_32 (TEGRA30_AUDIOCIF_BITS_32 << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT)
61
62#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT 8
63#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK (7 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
64#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_4 (TEGRA30_AUDIOCIF_BITS_4 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
65#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_8 (TEGRA30_AUDIOCIF_BITS_8 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
66#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_12 (TEGRA30_AUDIOCIF_BITS_12 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
67#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 (TEGRA30_AUDIOCIF_BITS_16 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
68#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_20 (TEGRA30_AUDIOCIF_BITS_20 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
69#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_24 (TEGRA30_AUDIOCIF_BITS_24 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
70#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_28 (TEGRA30_AUDIOCIF_BITS_28 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
71#define TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_32 (TEGRA30_AUDIOCIF_BITS_32 << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT)
72
73#define TEGRA30_AUDIOCIF_EXPAND_ZERO 0
74#define TEGRA30_AUDIOCIF_EXPAND_ONE 1
75#define TEGRA30_AUDIOCIF_EXPAND_LFSR 2
76
77#define TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT 6
78#define TEGRA30_AUDIOCIF_CTRL_EXPAND_MASK (3 << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
79#define TEGRA30_AUDIOCIF_CTRL_EXPAND_ZERO (TEGRA30_AUDIOCIF_EXPAND_ZERO << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
80#define TEGRA30_AUDIOCIF_CTRL_EXPAND_ONE (TEGRA30_AUDIOCIF_EXPAND_ONE << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
81#define TEGRA30_AUDIOCIF_CTRL_EXPAND_LFSR (TEGRA30_AUDIOCIF_EXPAND_LFSR << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT)
82
83#define TEGRA30_AUDIOCIF_STEREO_CONV_CH0 0
84#define TEGRA30_AUDIOCIF_STEREO_CONV_CH1 1
85#define TEGRA30_AUDIOCIF_STEREO_CONV_AVG 2
86
87#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT 4
88#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK (3 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
89#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH0 (TEGRA30_AUDIOCIF_STEREO_CONV_CH0 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
90#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
91#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
92
93#define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3
94
95#define TEGRA30_AUDIOCIF_DIRECTION_TX 0
96#define TEGRA30_AUDIOCIF_DIRECTION_RX 1
97
98#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT 2
99#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_MASK (1 << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
100#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX (TEGRA30_AUDIOCIF_DIRECTION_TX << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
101#define TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX (TEGRA30_AUDIOCIF_DIRECTION_RX << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT)
102
103#define TEGRA30_AUDIOCIF_TRUNCATE_ROUND 0
104#define TEGRA30_AUDIOCIF_TRUNCATE_CHOP 1
105
106#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT 1
107#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_MASK (1 << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
108#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_ROUND (TEGRA30_AUDIOCIF_TRUNCATE_ROUND << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
109#define TEGRA30_AUDIOCIF_CTRL_TRUNCATE_CHOP (TEGRA30_AUDIOCIF_TRUNCATE_CHOP << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT)
110
111#define TEGRA30_AUDIOCIF_MONO_CONV_ZERO 0
112#define TEGRA30_AUDIOCIF_MONO_CONV_COPY 1
113
114#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT 0
115#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_MASK (1 << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
116#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_ZERO (TEGRA30_AUDIOCIF_MONO_CONV_ZERO << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
117#define TEGRA30_AUDIOCIF_CTRL_MONO_CONV_COPY (TEGRA30_AUDIOCIF_MONO_CONV_COPY << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT)
118
119/* Registers within TEGRA30_AUDIO_CLUSTER_BASE */
120
121/* TEGRA30_AHUB_CHANNEL_CTRL */
122
123#define TEGRA30_AHUB_CHANNEL_CTRL 0x0
124#define TEGRA30_AHUB_CHANNEL_CTRL_STRIDE 0x20
125#define TEGRA30_AHUB_CHANNEL_CTRL_COUNT 4
126#define TEGRA30_AHUB_CHANNEL_CTRL_TX_EN (1 << 31)
127#define TEGRA30_AHUB_CHANNEL_CTRL_RX_EN (1 << 30)
128#define TEGRA30_AHUB_CHANNEL_CTRL_LOOPBACK (1 << 29)
129
130#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT 16
131#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK_US 0xff
132#define TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK (TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_TX_THRESHOLD_SHIFT)
133
134#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT 8
135#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK_US 0xff
136#define TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK (TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_RX_THRESHOLD_SHIFT)
137
138#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_EN (1 << 6)
139
140#define TEGRA30_PACK_8_4 2
141#define TEGRA30_PACK_16 3
142
143#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT 4
144#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK_US 3
145#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK (TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
146#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_8_4 (TEGRA30_PACK_8_4 << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
147#define TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16 (TEGRA30_PACK_16 << TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_SHIFT)
148
149#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_EN (1 << 2)
150
151#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT 0
152#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK_US 3
153#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK (TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_MASK_US << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
154#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_8_4 (TEGRA30_PACK_8_4 << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
155#define TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16 (TEGRA30_PACK_16 << TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_SHIFT)
156
157/* TEGRA30_AHUB_CHANNEL_CLEAR */
158
159#define TEGRA30_AHUB_CHANNEL_CLEAR 0x4
160#define TEGRA30_AHUB_CHANNEL_CLEAR_STRIDE 0x20
161#define TEGRA30_AHUB_CHANNEL_CLEAR_COUNT 4
162#define TEGRA30_AHUB_CHANNEL_CLEAR_TX_SOFT_RESET (1 << 31)
163#define TEGRA30_AHUB_CHANNEL_CLEAR_RX_SOFT_RESET (1 << 30)
164
165/* TEGRA30_AHUB_CHANNEL_STATUS */
166
167#define TEGRA30_AHUB_CHANNEL_STATUS 0x8
168#define TEGRA30_AHUB_CHANNEL_STATUS_STRIDE 0x20
169#define TEGRA30_AHUB_CHANNEL_STATUS_COUNT 4
170#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_SHIFT 24
171#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK_US 0xff
172#define TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK (TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_MASK_US << TEGRA30_AHUB_CHANNEL_STATUS_TX_FREE_SHIFT)
173#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_SHIFT 16
174#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK_US 0xff
175#define TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK (TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_MASK_US << TEGRA30_AHUB_CHANNEL_STATUS_RX_FREE_SHIFT)
176#define TEGRA30_AHUB_CHANNEL_STATUS_TX_TRIG (1 << 1)
177#define TEGRA30_AHUB_CHANNEL_STATUS_RX_TRIG (1 << 0)
178
179/* TEGRA30_AHUB_CHANNEL_TXFIFO */
180
181#define TEGRA30_AHUB_CHANNEL_TXFIFO 0xc
182#define TEGRA30_AHUB_CHANNEL_TXFIFO_STRIDE 0x20
183#define TEGRA30_AHUB_CHANNEL_TXFIFO_COUNT 4
184
185/* TEGRA30_AHUB_CHANNEL_RXFIFO */
186
187#define TEGRA30_AHUB_CHANNEL_RXFIFO 0x10
188#define TEGRA30_AHUB_CHANNEL_RXFIFO_STRIDE 0x20
189#define TEGRA30_AHUB_CHANNEL_RXFIFO_COUNT 4
190
191/* TEGRA30_AHUB_CIF_TX_CTRL */
192
193#define TEGRA30_AHUB_CIF_TX_CTRL 0x14
194#define TEGRA30_AHUB_CIF_TX_CTRL_STRIDE 0x20
195#define TEGRA30_AHUB_CIF_TX_CTRL_COUNT 4
196/* Uses field from TEGRA30_AUDIOCIF_CTRL_* */
197
198/* TEGRA30_AHUB_CIF_RX_CTRL */
199
200#define TEGRA30_AHUB_CIF_RX_CTRL 0x18
201#define TEGRA30_AHUB_CIF_RX_CTRL_STRIDE 0x20
202#define TEGRA30_AHUB_CIF_RX_CTRL_COUNT 4
203/* Uses field from TEGRA30_AUDIOCIF_CTRL_* */
204
205/* TEGRA30_AHUB_CONFIG_LINK_CTRL */
206
207#define TEGRA30_AHUB_CONFIG_LINK_CTRL 0x80
208#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_SHIFT 28
209#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK_US 0xf
210#define TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_MASTER_FIFO_FULL_CNT_SHIFT)
211#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT 16
212#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US 0xfff
213#define TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_TIMEOUT_CNT_SHIFT)
214#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT 5
215#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US 0xfff
216#define TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK (TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_MASK_US << TEGRA30_AHUB_CONFIG_LINK_CTRL_IDLE_CNT_SHIFT)
217#define TEGRA30_AHUB_CONFIG_LINK_CTRL_CG_EN (1 << 2)
218#define TEGRA30_AHUB_CONFIG_LINK_CTRL_CLEAR_TIMEOUT_CNTR (1 << 1)
219#define TEGRA30_AHUB_CONFIG_LINK_CTRL_SOFT_RESET (1 << 0)
220
221/* TEGRA30_AHUB_MISC_CTRL */
222
223#define TEGRA30_AHUB_MISC_CTRL 0x84
224#define TEGRA30_AHUB_MISC_CTRL_AUDIO_ACTIVE (1 << 31)
225#define TEGRA30_AHUB_MISC_CTRL_AUDIO_CG_EN (1 << 9)
226#define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT 0
227#define TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_MASK (0x1f << TEGRA30_AHUB_MISC_CTRL_AUDIO_OBS_SEL_SHIFT)
228
229/* TEGRA30_AHUB_APBDMA_LIVE_STATUS */
230
231#define TEGRA30_AHUB_APBDMA_LIVE_STATUS 0x88
232#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_CIF_FIFO_FULL (1 << 31)
233#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_CIF_FIFO_FULL (1 << 30)
234#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_CIF_FIFO_FULL (1 << 29)
235#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_CIF_FIFO_FULL (1 << 28)
236#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_CIF_FIFO_FULL (1 << 27)
237#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_CIF_FIFO_FULL (1 << 26)
238#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_CIF_FIFO_FULL (1 << 25)
239#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_CIF_FIFO_FULL (1 << 24)
240#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_CIF_FIFO_EMPTY (1 << 23)
241#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_CIF_FIFO_EMPTY (1 << 22)
242#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_CIF_FIFO_EMPTY (1 << 21)
243#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_CIF_FIFO_EMPTY (1 << 20)
244#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_CIF_FIFO_EMPTY (1 << 19)
245#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_CIF_FIFO_EMPTY (1 << 18)
246#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_CIF_FIFO_EMPTY (1 << 17)
247#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_CIF_FIFO_EMPTY (1 << 16)
248#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_DMA_FIFO_FULL (1 << 15)
249#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_DMA_FIFO_FULL (1 << 14)
250#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_DMA_FIFO_FULL (1 << 13)
251#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_DMA_FIFO_FULL (1 << 12)
252#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_DMA_FIFO_FULL (1 << 11)
253#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_DMA_FIFO_FULL (1 << 10)
254#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_DMA_FIFO_FULL (1 << 9)
255#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_DMA_FIFO_FULL (1 << 8)
256#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_RX_DMA_FIFO_EMPTY (1 << 7)
257#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH3_TX_DMA_FIFO_EMPTY (1 << 6)
258#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_RX_DMA_FIFO_EMPTY (1 << 5)
259#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH2_TX_DMA_FIFO_EMPTY (1 << 4)
260#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_RX_DMA_FIFO_EMPTY (1 << 3)
261#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH1_TX_DMA_FIFO_EMPTY (1 << 2)
262#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_RX_DMA_FIFO_EMPTY (1 << 1)
263#define TEGRA30_AHUB_APBDMA_LIVE_STATUS_CH0_TX_DMA_FIFO_EMPTY (1 << 0)
264
265/* TEGRA30_AHUB_I2S_LIVE_STATUS */
266
267#define TEGRA30_AHUB_I2S_LIVE_STATUS 0x8c
268#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_FULL (1 << 29)
269#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_FULL (1 << 28)
270#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_FULL (1 << 27)
271#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_FULL (1 << 26)
272#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_FULL (1 << 25)
273#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_FULL (1 << 24)
274#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_FULL (1 << 23)
275#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_FULL (1 << 22)
276#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_FULL (1 << 21)
277#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_FULL (1 << 20)
278#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_ENABLED (1 << 19)
279#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_ENABLED (1 << 18)
280#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_ENABLED (1 << 17)
281#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_ENABLED (1 << 16)
282#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_ENABLED (1 << 15)
283#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_ENABLED (1 << 14)
284#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_ENABLED (1 << 13)
285#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_ENABLED (1 << 12)
286#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_ENABLED (1 << 11)
287#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_ENABLED (1 << 10)
288#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_RX_FIFO_EMPTY (1 << 9)
289#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S4_TX_FIFO_EMPTY (1 << 8)
290#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_RX_FIFO_EMPTY (1 << 7)
291#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S3_TX_FIFO_EMPTY (1 << 6)
292#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_RX_FIFO_EMPTY (1 << 5)
293#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S2_TX_FIFO_EMPTY (1 << 4)
294#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_RX_FIFO_EMPTY (1 << 3)
295#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S1_TX_FIFO_EMPTY (1 << 2)
296#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_EMPTY (1 << 1)
297#define TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_EMPTY (1 << 0)
298
299/* TEGRA30_AHUB_DAM0_LIVE_STATUS */
300
301#define TEGRA30_AHUB_DAM_LIVE_STATUS 0x90
302#define TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE 0x8
303#define TEGRA30_AHUB_DAM_LIVE_STATUS_COUNT 3
304#define TEGRA30_AHUB_DAM_LIVE_STATUS_TX_ENABLED (1 << 26)
305#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1_ENABLED (1 << 25)
306#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0_ENABLED (1 << 24)
307#define TEGRA30_AHUB_DAM_LIVE_STATUS_TXFIFO_FULL (1 << 15)
308#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1FIFO_FULL (1 << 9)
309#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0FIFO_FULL (1 << 8)
310#define TEGRA30_AHUB_DAM_LIVE_STATUS_TXFIFO_EMPTY (1 << 7)
311#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX1FIFO_EMPTY (1 << 1)
312#define TEGRA30_AHUB_DAM_LIVE_STATUS_RX0FIFO_EMPTY (1 << 0)
313
314/* TEGRA30_AHUB_SPDIF_LIVE_STATUS */
315
316#define TEGRA30_AHUB_SPDIF_LIVE_STATUS 0xa8
317#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TX_ENABLED (1 << 11)
318#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RX_ENABLED (1 << 10)
319#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TX_ENABLED (1 << 9)
320#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RX_ENABLED (1 << 8)
321#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TXFIFO_FULL (1 << 7)
322#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RXFIFO_FULL (1 << 6)
323#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TXFIFO_FULL (1 << 5)
324#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RXFIFO_FULL (1 << 4)
325#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_TXFIFO_EMPTY (1 << 3)
326#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_USER_RXFIFO_EMPTY (1 << 2)
327#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_TXFIFO_EMPTY (1 << 1)
328#define TEGRA30_AHUB_SPDIF_LIVE_STATUS_DATA_RXFIFO_EMPTY (1 << 0)
329
330/* TEGRA30_AHUB_I2S_INT_MASK */
331
332#define TEGRA30_AHUB_I2S_INT_MASK 0xb0
333
334/* TEGRA30_AHUB_DAM_INT_MASK */
335
336#define TEGRA30_AHUB_DAM_INT_MASK 0xb4
337
338/* TEGRA30_AHUB_SPDIF_INT_MASK */
339
340#define TEGRA30_AHUB_SPDIF_INT_MASK 0xbc
341
342/* TEGRA30_AHUB_APBIF_INT_MASK */
343
344#define TEGRA30_AHUB_APBIF_INT_MASK 0xc0
345
346/* TEGRA30_AHUB_I2S_INT_STATUS */
347
348#define TEGRA30_AHUB_I2S_INT_STATUS 0xc8
349
350/* TEGRA30_AHUB_DAM_INT_STATUS */
351
352#define TEGRA30_AHUB_DAM_INT_STATUS 0xcc
353
354/* TEGRA30_AHUB_SPDIF_INT_STATUS */
355
356#define TEGRA30_AHUB_SPDIF_INT_STATUS 0xd4
357
358/* TEGRA30_AHUB_APBIF_INT_STATUS */
359
360#define TEGRA30_AHUB_APBIF_INT_STATUS 0xd8
361
362/* TEGRA30_AHUB_I2S_INT_SOURCE */
363
364#define TEGRA30_AHUB_I2S_INT_SOURCE 0xe0
365
366/* TEGRA30_AHUB_DAM_INT_SOURCE */
367
368#define TEGRA30_AHUB_DAM_INT_SOURCE 0xe4
369
370/* TEGRA30_AHUB_SPDIF_INT_SOURCE */
371
372#define TEGRA30_AHUB_SPDIF_INT_SOURCE 0xec
373
374/* TEGRA30_AHUB_APBIF_INT_SOURCE */
375
376#define TEGRA30_AHUB_APBIF_INT_SOURCE 0xf0
377
378/* TEGRA30_AHUB_I2S_INT_SET */
379
380#define TEGRA30_AHUB_I2S_INT_SET 0xf8
381
382/* TEGRA30_AHUB_DAM_INT_SET */
383
384#define TEGRA30_AHUB_DAM_INT_SET 0xfc
385
386/* TEGRA30_AHUB_SPDIF_INT_SET */
387
388#define TEGRA30_AHUB_SPDIF_INT_SET 0x100
389
390/* TEGRA30_AHUB_APBIF_INT_SET */
391
392#define TEGRA30_AHUB_APBIF_INT_SET 0x104
393
394/* Registers within TEGRA30_AHUB_BASE */
395
396#define TEGRA30_AHUB_AUDIO_RX 0x0
397#define TEGRA30_AHUB_AUDIO_RX_STRIDE 0x4
398#define TEGRA30_AHUB_AUDIO_RX_COUNT 17
399/* This register repeats once for each entry in enum tegra30_ahub_rxcif */
400/* The fields in this register are 1 bit per entry in tegra30_ahub_txcif */
401
402/* apbif register count */
403#define TEGRA30_APBIF_CACHE_REG_COUNT_PER_CHANNEL ((TEGRA30_AHUB_CIF_RX_CTRL>>2) + 1)
404#define TEGRA30_APBIF_CACHE_REG_COUNT ((TEGRA30_APBIF_CACHE_REG_COUNT_PER_CHANNEL + 1) * TEGRA30_AHUB_CHANNEL_CTRL_COUNT)
405
406/* cache index to be skipped */
407#define TEGRA30_APBIF_CACHE_REG_INDEX_RSVD TEGRA30_APBIF_CACHE_REG_COUNT_PER_CHANNEL
408#define TEGRA30_APBIF_CACHE_REG_INDEX_RSVD_STRIDE (TEGRA30_APBIF_CACHE_REG_COUNT_PER_CHANNEL + 1)
409
410/*
411 * Terminology:
412 * AHUB: Audio Hub; a cross-bar switch between the audio devices: DMA FIFOs,
413 * I2S controllers, SPDIF controllers, and DAMs.
414 * XBAR: The core cross-bar component of the AHUB.
415 * CIF: Client Interface; the HW module connecting an audio device to the
416 * XBAR.
417 * DAM: Digital Audio Mixer: A HW module that mixes multiple audio streams,
418 * possibly including sample-rate conversion.
419 *
420 * Each TX CIF transmits data into the XBAR. Each RX CIF can receive audio
421 * transmitted by a particular TX CIF.
422 *
423 * This driver is currently very simplistic; many HW features are not
424 * exposed; DAMs are not supported, only 16-bit stereo audio is supported,
425 * etc.
426 */
427
428enum tegra30_ahub_txcif {
429 TEGRA30_AHUB_TXCIF_APBIF_TX0,
430 TEGRA30_AHUB_TXCIF_APBIF_TX1,
431 TEGRA30_AHUB_TXCIF_APBIF_TX2,
432 TEGRA30_AHUB_TXCIF_APBIF_TX3,
433 TEGRA30_AHUB_TXCIF_I2S0_TX0,
434 TEGRA30_AHUB_TXCIF_I2S1_TX0,
435 TEGRA30_AHUB_TXCIF_I2S2_TX0,
436 TEGRA30_AHUB_TXCIF_I2S3_TX0,
437 TEGRA30_AHUB_TXCIF_I2S4_TX0,
438 TEGRA30_AHUB_TXCIF_DAM0_TX0,
439 TEGRA30_AHUB_TXCIF_DAM1_TX0,
440 TEGRA30_AHUB_TXCIF_DAM2_TX0,
441 TEGRA30_AHUB_TXCIF_SPDIF_TX0,
442 TEGRA30_AHUB_TXCIF_SPDIF_TX1,
443};
444
445enum tegra30_ahub_rxcif {
446 TEGRA30_AHUB_RXCIF_APBIF_RX0,
447 TEGRA30_AHUB_RXCIF_APBIF_RX1,
448 TEGRA30_AHUB_RXcIF_APBIF_RX2,
449 TEGRA30_AHUB_RXCIF_APBIF_RX3,
450 TEGRA30_AHUB_RXCIF_I2S0_RX0,
451 TEGRA30_AHUB_RXCIF_I2S1_RX0,
452 TEGRA30_AHUB_RXCIF_I2S2_RX0,
453 TEGRA30_AHUB_RXCIF_I2S3_RX0,
454 TEGRA30_AHUB_RXCIF_I2S4_RX0,
455 TEGRA30_AHUB_RXCIF_DAM0_RX0,
456 TEGRA30_AHUB_RXCIF_DAM0_RX1,
457 TEGRA30_AHUB_RXCIF_DAM1_RX0,
458 TEGRA30_AHUB_RXCIF_DAM2_RX1,
459 TEGRA30_AHUB_RXCIF_DAM3_RX0,
460 TEGRA30_AHUB_RXCIF_DAM3_RX1,
461 TEGRA30_AHUB_RXCIF_SPDIF_RX0,
462 TEGRA30_AHUB_RXCIF_SPDIF_RX1,
463};
464
465extern void tegra30_ahub_enable_clocks(void);
466extern void tegra30_ahub_disable_clocks(void);
467
468extern int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
469 unsigned long *fiforeg,
470 unsigned long *reqsel);
471extern int tegra30_ahub_set_rx_cif_channels(enum tegra30_ahub_rxcif rxcif,
472 unsigned int audio_ch,
473 unsigned int client_ch);
474extern int tegra30_ahub_enable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
475extern int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif);
476extern int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif);
477
478extern int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
479 unsigned long *fiforeg,
480 unsigned long *reqsel);
481extern int tegra30_ahub_set_tx_cif_channels(enum tegra30_ahub_txcif txcif,
482 unsigned int audio_ch,
483 unsigned int client_ch);
484extern int tegra30_ahub_enable_tx_fifo(enum tegra30_ahub_txcif txcif);
485extern int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif);
486extern int tegra30_ahub_free_tx_fifo(enum tegra30_ahub_txcif txcif);
487
488extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
489 enum tegra30_ahub_txcif txcif);
490extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
491
492#ifdef CONFIG_PM
493extern int tegra30_ahub_apbif_resume(void);
494#endif
495
496struct tegra30_ahub {
497 struct device *dev;
498 struct clk *clk_d_audio;
499 struct clk *clk_apbif;
500 resource_size_t apbif_addr;
501 void __iomem *apbif_regs;
502 void __iomem *audio_regs;
503 DECLARE_BITMAP(rx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
504 DECLARE_BITMAP(tx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
505 struct dentry *debug;
506#ifdef CONFIG_PM
507 u32 ahub_reg_cache[TEGRA30_AHUB_AUDIO_RX_COUNT];
508 u32 apbif_reg_cache[TEGRA30_APBIF_CACHE_REG_COUNT];
509#endif
510};
511
512#endif
diff --git a/sound/soc/tegra/tegra30_dam.c b/sound/soc/tegra/tegra30_dam.c
new file mode 100644
index 00000000000..d308179110c
--- /dev/null
+++ b/sound/soc/tegra/tegra30_dam.c
@@ -0,0 +1,650 @@
1/*
2 * tegra30_dam.c - Tegra 30 DAM driver
3 *
4 * Author: Nikesh Oswal <noswal@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, 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/clk.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/device.h>
27#include <linux/platform_device.h>
28#include <linux/seq_file.h>
29#include <linux/slab.h>
30#include <linux/io.h>
31#include <sound/soc.h>
32#include "tegra30_dam.h"
33#include "tegra30_ahub.h"
34
35#define DRV_NAME "tegra30-dam"
36
37static struct tegra30_dam_context *dams_cont_info[TEGRA30_NR_DAM_IFC];
38
39enum {
40 dam_ch_in0 = 0x0,
41 dam_ch_in1,
42 dam_ch_out,
43 dam_ch_maxnum
44} tegra30_dam_chtype;
45
46struct tegra30_dam_src_step_table step_table[] = {
47 { 8000, 44100, 80 },
48 { 8000, 48000, 1 },
49 { 16000, 44100, 160 },
50 { 16000, 48000, 1 },
51 { 44100, 8000, 441 },
52 { 48000, 8000, 0 },
53 { 44100, 16000, 441 },
54 { 48000, 16000, 0 },
55};
56
57static void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
58 int fsout);
59static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam,
60 int fsin);
61static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
62 int insample, int outsample);
63static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step);
64
65static inline void tegra30_dam_writel(struct tegra30_dam_context *dam,
66 u32 val, u32 reg)
67{
68#ifdef CONFIG_PM
69 dam->reg_cache[reg >> 2] = val;
70#endif
71 __raw_writel(val, dam->damregs + reg);
72}
73
74static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam, u32 reg)
75{
76 u32 val = __raw_readl(dam->damregs + reg);
77
78 return val;
79}
80
81#ifdef CONFIG_PM
82int tegra30_dam_resume(int ifc)
83{
84 int i = 0;
85 struct tegra30_dam_context *dam;
86
87 if (ifc >= TEGRA30_NR_DAM_IFC)
88 return -EINVAL;
89
90 dam = dams_cont_info[ifc];
91
92 if (dam->in_use) {
93 tegra30_dam_enable_clock(ifc);
94
95 for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
96 if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
97 (i == TEGRA30_DAM_CTRL_RSVD_10))
98 continue;
99
100 tegra30_dam_writel(dam, dam->reg_cache[i],
101 (i << 2));
102 }
103
104 tegra30_dam_disable_clock(ifc);
105 }
106
107 return 0;
108}
109#endif
110
111void tegra30_dam_disable_clock(int ifc)
112{
113 struct tegra30_dam_context *dam;
114
115 if (ifc >= TEGRA30_NR_DAM_IFC)
116 return;
117
118 dam = dams_cont_info[ifc];
119 clk_disable(dam->dam_clk);
120 tegra30_ahub_disable_clocks();
121}
122
123int tegra30_dam_enable_clock(int ifc)
124{
125 struct tegra30_dam_context *dam;
126
127 if (ifc >= TEGRA30_NR_DAM_IFC)
128 return -EINVAL;
129
130 dam = dams_cont_info[ifc];
131 tegra30_ahub_enable_clocks();
132 clk_enable(dam->dam_clk);
133
134 return 0;
135}
136
137#ifdef CONFIG_DEBUG_FS
138static int tegra30_dam_show(struct seq_file *s, void *unused)
139{
140#define REG(r) { r, #r }
141 static const struct {
142 int offset;
143 const char *name;
144 } regs[] = {
145 REG(TEGRA30_DAM_CTRL),
146 REG(TEGRA30_DAM_CLIP),
147 REG(TEGRA30_DAM_CLIP_THRESHOLD),
148 REG(TEGRA30_DAM_AUDIOCIF_OUT_CTRL),
149 REG(TEGRA30_DAM_CH0_CTRL),
150 REG(TEGRA30_DAM_CH0_CONV),
151 REG(TEGRA30_DAM_AUDIOCIF_CH0_CTRL),
152 REG(TEGRA30_DAM_CH1_CTRL),
153 REG(TEGRA30_DAM_CH1_CONV),
154 REG(TEGRA30_DAM_AUDIOCIF_CH1_CTRL),
155 };
156#undef REG
157
158 struct tegra30_dam_context *dam = s->private;
159 int i;
160
161 clk_enable(dam->dam_clk);
162
163 for (i = 0; i < ARRAY_SIZE(regs); i++) {
164 u32 val = tegra30_dam_readl(dam, regs[i].offset);
165 seq_printf(s, "%s = %08x\n", regs[i].name, val);
166 }
167
168 clk_disable(dam->dam_clk);
169
170 return 0;
171}
172
173static int tegra30_dam_debug_open(struct inode *inode, struct file *file)
174{
175 return single_open(file, tegra30_dam_show, inode->i_private);
176}
177
178static const struct file_operations tegra30_dam_debug_fops = {
179 .open = tegra30_dam_debug_open,
180 .read = seq_read,
181 .llseek = seq_lseek,
182 .release = single_release,
183};
184
185static void tegra30_dam_debug_add(struct tegra30_dam_context *dam, int id)
186{
187 char name[] = DRV_NAME ".0";
188
189 snprintf(name, sizeof(name), DRV_NAME".%1d", id);
190 dam->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
191 dam, &tegra30_dam_debug_fops);
192}
193
194static void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
195{
196 if (dam->debug)
197 debugfs_remove(dam->debug);
198}
199#else
200static inline void tegra30_dam_debug_add(struct tegra30_dam_context *dam,
201 int id)
202{
203}
204
205static inline void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
206{
207}
208#endif
209
210int tegra30_dam_allocate_controller()
211{
212 int i = 0;
213 struct tegra30_dam_context *dam = NULL;
214
215 for (i = 0; i < TEGRA30_NR_DAM_IFC; i++) {
216
217 dam = dams_cont_info[i];
218
219 if (!dam->in_use) {
220 dam->in_use = true;
221 return i;
222 }
223 }
224
225 return -ENOENT;
226}
227
228int tegra30_dam_allocate_channel(int ifc, int chid)
229{
230 struct tegra30_dam_context *dam = NULL;
231
232 if (ifc >= TEGRA30_NR_DAM_IFC)
233 return -EINVAL;
234
235 dam = dams_cont_info[ifc];
236
237 if (!dam->ch_alloc[chid]) {
238 dam->ch_alloc[chid] = true;
239 return 0;
240 }
241
242 return -ENOENT;
243}
244
245int tegra30_dam_free_channel(int ifc, int chid)
246{
247 struct tegra30_dam_context *dam = NULL;
248
249 if (ifc >= TEGRA30_NR_DAM_IFC)
250 return -EINVAL;
251
252 dam = dams_cont_info[ifc];
253
254 if (dam->ch_alloc[chid]) {
255 dam->ch_alloc[chid] = false;
256 return 0;
257 }
258
259 return -EINVAL;
260}
261
262int tegra30_dam_free_controller(int ifc)
263{
264 struct tegra30_dam_context *dam = NULL;
265
266 if (ifc >= TEGRA30_NR_DAM_IFC)
267 return -EINVAL;
268
269 dam = dams_cont_info[ifc];
270
271 if (!dam->ch_alloc[dam_ch_in0] &&
272 !dam->ch_alloc[dam_ch_in1]) {
273 dam->in_use = false;
274 return 0;
275 }
276
277 return -EINVAL;
278}
279
280void tegra30_dam_set_samplerate(int ifc, int chid, int samplerate)
281{
282 struct tegra30_dam_context *dam = dams_cont_info[ifc];
283
284 if (ifc >= TEGRA30_NR_DAM_IFC)
285 return;
286
287 switch (chid) {
288 case dam_ch_in0:
289 tegra30_dam_set_input_samplerate(dam, samplerate);
290 dam->ch_insamplerate[dam_ch_in0] = samplerate;
291 tegra30_dam_set_step_reset(dam, samplerate, dam->outsamplerate);
292 break;
293 case dam_ch_in1:
294 if (samplerate != dam->outsamplerate)
295 return;
296 dam->ch_insamplerate[dam_ch_in1] = samplerate;
297 break;
298 case dam_ch_out:
299 tegra30_dam_set_output_samplerate(dam, samplerate);
300 dam->outsamplerate = samplerate;
301 break;
302 default:
303 break;
304 }
305}
306
307void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
308 int fsout)
309{
310 u32 val;
311
312 val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
313 val &= ~TEGRA30_DAM_CTRL_FSOUT_MASK;
314
315 switch (fsout) {
316 case TEGRA30_AUDIO_SAMPLERATE_8000:
317 val |= TEGRA30_DAM_CTRL_FSOUT_FS8;
318 break;
319 case TEGRA30_AUDIO_SAMPLERATE_16000:
320 val |= TEGRA30_DAM_CTRL_FSOUT_FS16;
321 break;
322 case TEGRA30_AUDIO_SAMPLERATE_44100:
323 val |= TEGRA30_DAM_CTRL_FSOUT_FS44;
324 break;
325 case TEGRA30_AUDIO_SAMPLERATE_48000:
326 val |= TEGRA30_DAM_CTRL_FSOUT_FS48;
327 break;
328 default:
329 break;
330 }
331
332 tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
333}
334
335void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin)
336{
337 u32 val;
338
339 val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
340 val &= ~TEGRA30_DAM_CH0_CTRL_FSIN_MASK;
341
342 switch (fsin) {
343 case TEGRA30_AUDIO_SAMPLERATE_8000:
344 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS8;
345 break;
346 case TEGRA30_AUDIO_SAMPLERATE_16000:
347 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS16;
348 break;
349 case TEGRA30_AUDIO_SAMPLERATE_44100:
350 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS44;
351 break;
352 case TEGRA30_AUDIO_SAMPLERATE_48000:
353 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS48;
354 break;
355 default:
356 break;
357 }
358
359 tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
360}
361
362int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
363 int insample, int outsample)
364{
365 int step_reset = 0;
366 int i = 0;
367
368 for (i = 0; i < ARRAY_SIZE(step_table); i++) {
369 if ((insample == step_table[i].insample) &&
370 (outsample == step_table[i].outsample))
371 step_reset = step_table[i].stepreset;
372 }
373
374 tegra30_dam_ch0_set_step(dam, step_reset);
375
376 return 0;
377}
378
379void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
380{
381 u32 val;
382
383 val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
384 val &= ~TEGRA30_DAM_CH0_CTRL_STEP_MASK;
385 val |= step << TEGRA30_DAM_CH0_CTRL_STEP_SHIFT;
386 tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
387}
388
389int tegra30_dam_set_gain(int ifc, int chid, int gain)
390{
391
392 if (ifc >= TEGRA30_NR_DAM_IFC)
393 return -EINVAL;
394
395 switch (chid) {
396 case dam_ch_in0:
397 tegra30_dam_writel(dams_cont_info[ifc], gain,
398 TEGRA30_DAM_CH0_CONV);
399 break;
400 case dam_ch_in1:
401 tegra30_dam_writel(dams_cont_info[ifc], gain,
402 TEGRA30_DAM_CH1_CONV);
403 break;
404 default:
405 break;
406 }
407
408 return 0;
409}
410
411int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
412 unsigned int audio_bits, unsigned int client_channels,
413 unsigned int client_bits)
414{
415 unsigned int reg;
416 unsigned int value = 0;
417
418 if (ifc >= TEGRA30_NR_DAM_IFC)
419 return -EINVAL;
420
421 /*ch0 takes input as mono/16bit always*/
422 if ((chid == dam_ch_in0) &&
423 ((client_channels != 1) || (client_bits != 16)))
424 return -EINVAL;
425
426 value |= TEGRA30_CIF_MONOCONV_COPY;
427 value |= TEGRA30_CIF_STEREOCONV_CH0;
428 value |= (audio_channels-1) << TEGRA30_AUDIO_CHANNELS_SHIFT;
429 value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
430 value |= (client_channels-1) << TEGRA30_CLIENT_CHANNELS_SHIFT;
431 value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
432
433 switch (chid) {
434 case dam_ch_out:
435 value |= TEGRA30_CIF_DIRECTION_TX;
436 reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
437 break;
438 case dam_ch_in0:
439 value |= TEGRA30_CIF_DIRECTION_RX;
440 reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
441 break;
442 case dam_ch_in1:
443 value |= TEGRA30_CIF_DIRECTION_RX;
444 reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
445 break;
446 default:
447 return -EINVAL;
448 }
449
450 tegra30_dam_writel(dams_cont_info[ifc], value, reg);
451
452 return 0;
453}
454
455void tegra30_dam_enable(int ifc, int on, int chid)
456{
457 u32 old_val, val, enreg;
458 struct tegra30_dam_context *dam = dams_cont_info[ifc];
459
460 if (ifc >= TEGRA30_NR_DAM_IFC)
461 return;
462
463 if (chid == dam_ch_in0)
464 enreg = TEGRA30_DAM_CH0_CTRL;
465 else
466 enreg = TEGRA30_DAM_CH1_CTRL;
467
468 old_val = val = tegra30_dam_readl(dam, enreg);
469
470 if (on) {
471 if (!dam->ch_enable_refcnt[chid]++)
472 val |= TEGRA30_DAM_CH0_CTRL_EN;
473 } else if (dam->ch_enable_refcnt[chid]) {
474 dam->ch_enable_refcnt[chid]--;
475 if (!dam->ch_enable_refcnt[chid])
476 val &= ~TEGRA30_DAM_CH0_CTRL_EN;
477 }
478
479 if (val != old_val)
480 tegra30_dam_writel(dam, val, enreg);
481
482 old_val = val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
483
484 if (dam->ch_enable_refcnt[dam_ch_in0] ||
485 dam->ch_enable_refcnt[dam_ch_in1])
486 val |= TEGRA30_DAM_CTRL_DAM_EN;
487 else
488 val &= ~TEGRA30_DAM_CTRL_DAM_EN;
489
490 if (old_val != val)
491 tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
492}
493
494void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
495{
496 u32 val;
497
498 val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
499 val &= ~TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK;
500 val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
501 tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
502}
503
504void tegra30_dam_ch1_set_datasync(struct tegra30_dam_context *dam, int datasync)
505{
506 u32 val;
507
508 val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL);
509 val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK;
510 val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
511 tegra30_dam_writel(dam, val, TEGRA30_DAM_CH1_CTRL);
512}
513
514void tegra30_dam_enable_clip_counter(struct tegra30_dam_context *dam, int on)
515{
516 u32 val;
517
518 val = tegra30_dam_readl(dam, TEGRA30_DAM_CLIP);
519 val &= ~TEGRA30_DAM_CLIP_COUNTER_ENABLE;
520 val |= on ? TEGRA30_DAM_CLIP_COUNTER_ENABLE : 0;
521 tegra30_dam_writel(dam, val, TEGRA30_DAM_CLIP);
522}
523
524static int __devinit tegra30_dam_probe(struct platform_device *pdev)
525{
526 struct resource *res, *region;
527 struct tegra30_dam_context *dam;
528 int ret = 0;
529#ifdef CONFIG_PM
530 int i;
531#endif
532 int clkm_rate;
533
534 if ((pdev->id < 0) ||
535 (pdev->id >= TEGRA30_NR_DAM_IFC)) {
536 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
537 return -EINVAL;
538 }
539
540 dams_cont_info[pdev->id] = devm_kzalloc(&pdev->dev,
541 sizeof(struct tegra30_dam_context),
542 GFP_KERNEL);
543 if (!dams_cont_info[pdev->id]) {
544 dev_err(&pdev->dev, "Can't allocate dam context\n");
545 ret = -ENOMEM;
546 goto exit;
547 }
548 dam = dams_cont_info[pdev->id];
549
550 dam->dam_clk = clk_get(&pdev->dev, NULL);
551 if (IS_ERR(dam->dam_clk)) {
552 dev_err(&pdev->dev, "Can't retrieve dam clock\n");
553 ret = PTR_ERR(dam->dam_clk);
554 goto err_free;
555 }
556 clkm_rate = clk_get_rate(clk_get_parent(dam->dam_clk));
557 while (clkm_rate > 12000000)
558 clkm_rate >>= 1;
559
560 clk_set_rate(dam->dam_clk,clkm_rate);
561
562 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
563 if (!res) {
564 dev_err(&pdev->dev, "No memory 0 resource\n");
565 ret = -ENODEV;
566 goto err_clk_put_dam;
567 }
568
569 region = devm_request_mem_region(&pdev->dev, res->start,
570 resource_size(res), pdev->name);
571 if (!region) {
572 dev_err(&pdev->dev, "Memory region 0 already claimed\n");
573 ret = -EBUSY;
574 goto err_clk_put_dam;
575 }
576
577 dam->damregs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
578 if (!dam->damregs) {
579 dev_err(&pdev->dev, "ioremap 0 failed\n");
580 ret = -ENOMEM;
581 goto err_clk_put_dam;
582 }
583
584#ifdef CONFIG_PM
585 /* cache the POR values of DAM regs*/
586 tegra30_dam_enable_clock(pdev->id);
587
588 for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
589 if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
590 (i == TEGRA30_DAM_CTRL_RSVD_10))
591 continue;
592
593 dam->reg_cache[i] =
594 tegra30_dam_readl(dam, i << 2);
595 }
596
597 tegra30_dam_disable_clock(pdev->id);
598#endif
599
600 platform_set_drvdata(pdev, dam);
601
602 tegra30_dam_debug_add(dam, pdev->id);
603
604 return 0;
605
606err_clk_put_dam:
607 clk_put(dam->dam_clk);
608err_free:
609 dams_cont_info[pdev->id] = NULL;
610exit:
611 return ret;
612}
613
614static int __devexit tegra30_dam_remove(struct platform_device *pdev)
615{
616 struct tegra30_dam_context *dam;
617
618 dam = platform_get_drvdata(pdev);
619 clk_put(dam->dam_clk);
620 tegra30_dam_debug_remove(dam);
621 dams_cont_info[pdev->id] = NULL;
622
623 return 0;
624}
625
626static struct platform_driver tegra30_dam_driver = {
627 .probe = tegra30_dam_probe,
628 .remove = __devexit_p(tegra30_dam_remove),
629 .driver = {
630 .name = DRV_NAME,
631 .owner = THIS_MODULE,
632 },
633};
634
635static int __init tegra30_dam_modinit(void)
636{
637 return platform_driver_register(&tegra30_dam_driver);
638}
639module_init(tegra30_dam_modinit);
640
641static void __exit tegra30_dam_modexit(void)
642{
643 platform_driver_unregister(&tegra30_dam_driver);
644}
645module_exit(tegra30_dam_modexit);
646
647MODULE_AUTHOR("Nikesh Oswal <noswal@nvidia.com>");
648MODULE_DESCRIPTION("Tegra 30 DAM driver");
649MODULE_LICENSE("GPL");
650MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra30_dam.h b/sound/soc/tegra/tegra30_dam.h
new file mode 100644
index 00000000000..371e8139eec
--- /dev/null
+++ b/sound/soc/tegra/tegra30_dam.h
@@ -0,0 +1,163 @@
1/*
2 * tegra30_dam.h - Tegra 30 DAM driver.
3 *
4 * Author: Nikesh Oswal <noswal@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, 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#ifndef __TEGRA30_DAM_H
24#define __TEGRA30_DAM_H
25
26/* Register offsets from TEGRA30_DAM*_BASE */
27#define TEGRA30_DAM_CTRL 0
28#define TEGRA30_DAM_CLIP 4
29#define TEGRA30_DAM_CLIP_THRESHOLD 8
30#define TEGRA30_DAM_AUDIOCIF_OUT_CTRL 0x0C
31#define TEGRA30_DAM_CH0_CTRL 0x10
32#define TEGRA30_DAM_CH0_CONV 0x14
33#define TEGRA30_DAM_AUDIOCIF_CH0_CTRL 0x1C
34#define TEGRA30_DAM_CH1_CTRL 0x20
35#define TEGRA30_DAM_CH1_CONV 0x24
36#define TEGRA30_DAM_AUDIOCIF_CH1_CTRL 0x2C
37#define TEGRA30_DAM_CTRL_REGINDEX (TEGRA30_DAM_AUDIOCIF_CH1_CTRL >> 2)
38#define TEGRA30_DAM_CTRL_RSVD_6 6
39#define TEGRA30_DAM_CTRL_RSVD_10 10
40
41#define TEGRA30_NR_DAM_IFC 3
42
43#define TEGRA30_DAM_NUM_INPUT_CHANNELS 2
44
45/* Fields in TEGRA30_DAM_CTRL */
46#define TEGRA30_DAM_CTRL_SOFT_RESET_ENABLE (1 << 31)
47#define TEGRA30_DAM_CTRL_FSOUT_SHIFT 4
48#define TEGRA30_DAM_CTRL_FSOUT_MASK (0xf << TEGRA30_DAM_CTRL_FSOUT_SHIFT)
49#define TEGRA30_DAM_FS_8KHZ 0
50#define TEGRA30_DAM_FS_16KHZ 1
51#define TEGRA30_DAM_FS_44KHZ 2
52#define TEGRA30_DAM_FS_48KHZ 3
53#define TEGRA30_DAM_CTRL_FSOUT_FS8 (TEGRA30_DAM_FS_8KHZ << TEGRA30_DAM_CTRL_FSOUT_SHIFT)
54#define TEGRA30_DAM_CTRL_FSOUT_FS16 (TEGRA30_DAM_FS_16KHZ << TEGRA30_DAM_CTRL_FSOUT_SHIFT)
55#define TEGRA30_DAM_CTRL_FSOUT_FS44 (TEGRA30_DAM_FS_44KHZ << TEGRA30_DAM_CTRL_FSOUT_SHIFT)
56#define TEGRA30_DAM_CTRL_FSOUT_FS48 (TEGRA30_DAM_FS_48KHZ << TEGRA30_DAM_CTRL_FSOUT_SHIFT)
57#define TEGRA30_DAM_CTRL_CG_EN (1 << 1)
58#define TEGRA30_DAM_CTRL_DAM_EN (1 << 0)
59
60
61/* Fields in TEGRA30_DAM_CLIP */
62#define TEGRA30_DAM_CLIP_COUNTER_ENABLE (1 << 31)
63#define TEGRA30_DAM_CLIP_COUNT_MASK 0x7fffffff
64
65
66/* Fields in TEGRA30_DAM_CH0_CTRL */
67#define TEGRA30_STEP_RESET 1
68#define TEGRA30_DAM_DATA_SYNC 1
69#define TEGRA30_DAM_DATA_SYNC_SHIFT 4
70#define TEGRA30_DAM_CH0_CTRL_FSIN_SHIFT 8
71#define TEGRA30_DAM_CH0_CTRL_STEP_SHIFT 16
72#define TEGRA30_DAM_CH0_CTRL_STEP_MASK (0xffff << 16)
73#define TEGRA30_DAM_CH0_CTRL_STEP_RESET (TEGRA30_STEP_RESET << 16)
74#define TEGRA30_DAM_CH0_CTRL_FSIN_MASK (0xf << 8)
75#define TEGRA30_DAM_CH0_CTRL_FSIN_FS8 (TEGRA30_DAM_FS_8KHZ << 8)
76#define TEGRA30_DAM_CH0_CTRL_FSIN_FS16 (TEGRA30_DAM_FS_16KHZ << 8)
77#define TEGRA30_DAM_CH0_CTRL_FSIN_FS44 (TEGRA30_DAM_FS_44KHZ << 8)
78#define TEGRA30_DAM_CH0_CTRL_FSIN_FS48 (TEGRA30_DAM_FS_48KHZ << 8)
79#define TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK (0xf << TEGRA30_DAM_DATA_SYNC_SHIFT)
80#define TEGRA30_DAM_CH0_CTRL_DATA_SYNC (TEGRA30_DAM_DATA_SYNC << TEGRA30_DAM_DATA_SYNC_SHIFT)
81#define TEGRA30_DAM_CH0_CTRL_EN (1 << 0)
82
83
84/* Fields in TEGRA30_DAM_CH0_CONV */
85#define TEGRA30_DAM_GAIN 1
86#define TEGRA30_DAM_GAIN_SHIFT 0
87#define TEGRA30_DAM_CH0_CONV_GAIN (TEGRA30_DAM_GAIN << TEGRA30_DAM_GAIN_SHIFT)
88
89/* Fields in TEGRA30_DAM_CH1_CTRL */
90#define TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK (0xf << TEGRA30_DAM_DATA_SYNC_SHIFT)
91#define TEGRA30_DAM_CH1_CTRL_DATA_SYNC (TEGRA30_DAM_DATA_SYNC << TEGRA30_DAM_DATA_SYNC_SHIFT)
92#define TEGRA30_DAM_CH1_CTRL_EN (1 << 0)
93
94/* Fields in TEGRA30_DAM_CH1_CONV */
95#define TEGRA30_DAM_CH1_CONV_GAIN (TEGRA30_DAM_GAIN << TEGRA30_DAM_GAIN_SHIFT)
96
97#define TEGRA30_AUDIO_CHANNELS_SHIFT 24
98#define TEGRA30_AUDIO_CHANNELS_MASK (7 << TEGRA30_AUDIO_CHANNELS_SHIFT)
99#define TEGRA30_CLIENT_CHANNELS_SHIFT 16
100#define TEGRA30_CLIENT_CHANNELS_MASK (7 << TEGRA30_CLIENT_CHANNELS_SHIFT)
101#define TEGRA30_AUDIO_BITS_SHIFT 12
102#define TEGRA30_AUDIO_BITS_MASK (7 << TEGRA30_AUDIO_BITS_SHIFT)
103#define TEGRA30_CLIENT_BITS_SHIFT 8
104#define TEGRA30_CLIENT_BITS_MASK (7 << TEGRA30_CLIENT_BITS_SHIFT)
105#define TEGRA30_CIF_DIRECTION_TX (0 << 2)
106#define TEGRA30_CIF_DIRECTION_RX (1 << 2)
107#define TEGRA30_CIF_BIT24 5
108#define TEGRA30_CIF_BIT16 3
109#define TEGRA30_CIF_CH1 0
110#define TEGRA30_CIF_MONOCONV_COPY (1<<0)
111#define TEGRA30_CIF_STEREOCONV_CH0 (0<<4)
112
113/*
114* Audio Samplerates
115*/
116#define TEGRA30_AUDIO_SAMPLERATE_8000 8000
117#define TEGRA30_AUDIO_SAMPLERATE_16000 16000
118#define TEGRA30_AUDIO_SAMPLERATE_44100 44100
119#define TEGRA30_AUDIO_SAMPLERATE_48000 48000
120
121#define TEGRA30_DAM_CHIN0_SRC 0
122#define TEGRA30_DAM_CHIN1 1
123#define TEGRA30_DAM_CHOUT 2
124#define TEGRA30_DAM_ENABLE 1
125#define TEGRA30_DAM_DISABLE 0
126
127struct tegra30_dam_context {
128 int outsamplerate;
129 bool ch_alloc[TEGRA30_DAM_NUM_INPUT_CHANNELS];
130 int ch_enable_refcnt[TEGRA30_DAM_NUM_INPUT_CHANNELS];
131 int ch_insamplerate[TEGRA30_DAM_NUM_INPUT_CHANNELS];
132#ifdef CONFIG_PM
133 int reg_cache[TEGRA30_DAM_CTRL_REGINDEX + 1];
134#endif
135 struct clk *dam_clk;
136 bool in_use;
137 void __iomem *damregs;
138 struct dentry *debug;
139};
140
141struct tegra30_dam_src_step_table {
142 int insample;
143 int outsample;
144 int stepreset;
145};
146
147#ifdef CONFIG_PM
148int tegra30_dam_resume(int ifc);
149#endif
150void tegra30_dam_disable_clock(int ifc);
151int tegra30_dam_enable_clock(int ifc);
152int tegra30_dam_allocate_controller(void);
153int tegra30_dam_allocate_channel(int ifc, int chid);
154int tegra30_dam_free_channel(int ifc, int chid);
155int tegra30_dam_free_controller(int ifc);
156void tegra30_dam_set_samplerate(int ifc, int chtype, int samplerate);
157int tegra30_dam_set_gain(int ifc, int chtype, int gain);
158int tegra30_dam_set_acif(int ifc, int chtype, unsigned int audio_channels,
159 unsigned int audio_bits, unsigned int client_channels,
160 unsigned int client_bits);
161void tegra30_dam_enable(int ifc, int on, int chtype);
162
163#endif
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
new file mode 100644
index 00000000000..02d1038ea36
--- /dev/null
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -0,0 +1,949 @@
1/*
2 * tegra30_i2s.c - Tegra 30 I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (c) 2010-2011, NVIDIA Corporation.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <linux/clk.h>
32#include <linux/module.h>
33#include <linux/debugfs.h>
34#include <linux/device.h>
35#include <linux/platform_device.h>
36#include <linux/seq_file.h>
37#include <linux/slab.h>
38#include <linux/io.h>
39#include <mach/iomap.h>
40#include <sound/core.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "tegra30_ahub.h"
46#include "tegra30_dam.h"
47#include "tegra30_i2s.h"
48
49#define DRV_NAME "tegra30-i2s"
50
51static struct tegra30_i2s i2scont[TEGRA30_NR_I2S_IFC];
52
53static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
54{
55#ifdef CONFIG_PM
56 i2s->reg_cache[reg >> 2] = val;
57#endif
58 __raw_writel(val, i2s->regs + reg);
59}
60
61static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
62{
63 return __raw_readl(i2s->regs + reg);
64}
65
66static void tegra30_i2s_enable_clocks(struct tegra30_i2s *i2s)
67{
68 tegra30_ahub_enable_clocks();
69 clk_enable(i2s->clk_i2s);
70}
71
72static void tegra30_i2s_disable_clocks(struct tegra30_i2s *i2s)
73{
74 clk_disable(i2s->clk_i2s);
75 tegra30_ahub_disable_clocks();
76}
77
78#ifdef CONFIG_DEBUG_FS
79static int tegra30_i2s_show(struct seq_file *s, void *unused)
80{
81#define REG(r) { r, #r }
82 static const struct {
83 int offset;
84 const char *name;
85 } regs[] = {
86 REG(TEGRA30_I2S_CTRL),
87 REG(TEGRA30_I2S_TIMING),
88 REG(TEGRA30_I2S_OFFSET),
89 REG(TEGRA30_I2S_CH_CTRL),
90 REG(TEGRA30_I2S_SLOT_CTRL),
91 REG(TEGRA30_I2S_CIF_TX_CTRL),
92 REG(TEGRA30_I2S_CIF_RX_CTRL),
93 REG(TEGRA30_I2S_FLOWCTL),
94 REG(TEGRA30_I2S_TX_STEP),
95 REG(TEGRA30_I2S_FLOW_STATUS),
96 REG(TEGRA30_I2S_FLOW_TOTAL),
97 REG(TEGRA30_I2S_FLOW_OVER),
98 REG(TEGRA30_I2S_FLOW_UNDER),
99 REG(TEGRA30_I2S_LCOEF_1_4_0),
100 REG(TEGRA30_I2S_LCOEF_1_4_1),
101 REG(TEGRA30_I2S_LCOEF_1_4_2),
102 REG(TEGRA30_I2S_LCOEF_1_4_3),
103 REG(TEGRA30_I2S_LCOEF_1_4_4),
104 REG(TEGRA30_I2S_LCOEF_1_4_5),
105 REG(TEGRA30_I2S_LCOEF_2_4_0),
106 REG(TEGRA30_I2S_LCOEF_2_4_1),
107 REG(TEGRA30_I2S_LCOEF_2_4_2),
108 };
109#undef REG
110
111 struct tegra30_i2s *i2s = s->private;
112 int i;
113
114 tegra30_i2s_enable_clocks(i2s);
115
116 for (i = 0; i < ARRAY_SIZE(regs); i++) {
117 u32 val = tegra30_i2s_read(i2s, regs[i].offset);
118 seq_printf(s, "%s = %08x\n", regs[i].name, val);
119 }
120
121 tegra30_i2s_disable_clocks(i2s);
122
123 return 0;
124}
125
126static int tegra30_i2s_debug_open(struct inode *inode, struct file *file)
127{
128 return single_open(file, tegra30_i2s_show, inode->i_private);
129}
130
131static const struct file_operations tegra30_i2s_debug_fops = {
132 .open = tegra30_i2s_debug_open,
133 .read = seq_read,
134 .llseek = seq_lseek,
135 .release = single_release,
136};
137
138static void tegra30_i2s_debug_add(struct tegra30_i2s *i2s, int id)
139{
140 char name[] = DRV_NAME ".0";
141
142 snprintf(name, sizeof(name), DRV_NAME".%1d", id);
143 i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
144 i2s, &tegra30_i2s_debug_fops);
145}
146
147static void tegra30_i2s_debug_remove(struct tegra30_i2s *i2s)
148{
149 if (i2s->debug)
150 debugfs_remove(i2s->debug);
151}
152#else
153static inline void tegra30_i2s_debug_add(struct tegra30_i2s *i2s, int id)
154{
155}
156
157static inline void tegra30_i2s_debug_remove(struct tegra30_i2s *i2s)
158{
159}
160#endif
161
162int tegra30_i2s_startup(struct snd_pcm_substream *substream,
163 struct snd_soc_dai *dai)
164{
165 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
166 int ret;
167
168 tegra30_i2s_enable_clocks(i2s);
169
170 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
171 /* increment the playback ref count */
172 i2s->playback_ref_count++;
173
174 ret = tegra30_ahub_allocate_tx_fifo(&i2s->txcif,
175 &i2s->playback_dma_data.addr,
176 &i2s->playback_dma_data.req_sel);
177 i2s->playback_dma_data.wrap = 4;
178 i2s->playback_dma_data.width = 32;
179
180 if (!i2s->is_dam_used)
181 tegra30_ahub_set_rx_cif_source(
182 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
183 i2s->txcif);
184 } else {
185 ret = tegra30_ahub_allocate_rx_fifo(&i2s->rxcif,
186 &i2s->capture_dma_data.addr,
187 &i2s->capture_dma_data.req_sel);
188 i2s->capture_dma_data.wrap = 4;
189 i2s->capture_dma_data.width = 32;
190 tegra30_ahub_set_rx_cif_source(i2s->rxcif,
191 TEGRA30_AHUB_TXCIF_I2S0_TX0 + i2s->id);
192 }
193
194 tegra30_i2s_disable_clocks(i2s);
195
196 return ret;
197}
198
199void tegra30_i2s_shutdown(struct snd_pcm_substream *substream,
200 struct snd_soc_dai *dai)
201{
202 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
203
204 tegra30_i2s_enable_clocks(i2s);
205
206 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
207 if (i2s->playback_ref_count == 1)
208 tegra30_ahub_unset_rx_cif_source(
209 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id);
210
211 /* free the apbif dma channel*/
212 tegra30_ahub_free_tx_fifo(i2s->txcif);
213
214 /* decrement the playback ref count */
215 i2s->playback_ref_count--;
216 } else {
217 tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
218 tegra30_ahub_free_rx_fifo(i2s->rxcif);
219 }
220
221 tegra30_i2s_disable_clocks(i2s);
222}
223
224static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
225 unsigned int fmt)
226{
227 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
228
229 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
230 case SND_SOC_DAIFMT_NB_NF:
231 break;
232 default:
233 return -EINVAL;
234 }
235
236 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE;
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBS_CFS:
239 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
240 break;
241 case SND_SOC_DAIFMT_CBM_CFM:
242 break;
243 default:
244 return -EINVAL;
245 }
246
247 i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
248 TEGRA30_I2S_CTRL_LRCK_MASK);
249 i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK;
250 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
251 case SND_SOC_DAIFMT_DSP_A:
252 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
253 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
254 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
255 break;
256 case SND_SOC_DAIFMT_DSP_B:
257 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
258 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
259 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
260 break;
261 case SND_SOC_DAIFMT_I2S:
262 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
263 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
264 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
265 break;
266 case SND_SOC_DAIFMT_RIGHT_J:
267 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
268 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
269 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
270 break;
271 case SND_SOC_DAIFMT_LEFT_J:
272 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
273 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
274 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
275 break;
276 default:
277 return -EINVAL;
278 }
279
280 return 0;
281}
282
283static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
284 struct snd_pcm_hw_params *params,
285 struct snd_soc_dai *dai)
286{
287 struct device *dev = substream->pcm->card->dev;
288 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
289 u32 val;
290 int ret, sample_size, srate, i2sclock, bitcnt, sym_bitclk;
291 int i2s_client_ch;
292
293 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
294 switch (params_format(params)) {
295 case SNDRV_PCM_FORMAT_S16_LE:
296 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
297 sample_size = 16;
298 break;
299 default:
300 return -EINVAL;
301 }
302
303 srate = params_rate(params);
304
305 if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
306 i2sclock = srate * params_channels(params) * sample_size;
307
308 /* Additional "* 4" is needed for FSYNC mode */
309 if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
310 i2sclock *= 4;
311 ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
312 if (ret) {
313 dev_err(dev, "Can't set parent of I2S clock\n");
314 return ret;
315 }
316
317 ret = clk_set_rate(i2s->clk_i2s, i2sclock);
318 if (ret) {
319 dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
320 return ret;
321 }
322
323 if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) {
324 bitcnt = (i2sclock / srate) - 1;
325 sym_bitclk = !(i2sclock % srate);
326 } else {
327 bitcnt = (i2sclock / (2 * srate)) - 1;
328 sym_bitclk = !(i2sclock % (2 * srate));
329 }
330 val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
331
332 if (!sym_bitclk)
333 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
334
335 tegra30_i2s_enable_clocks(i2s);
336
337 tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
338 } else {
339 i2sclock = srate * params_channels(params) * sample_size;
340
341 /* Additional "* 2" is needed for FSYNC mode */
342 if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
343 i2sclock *= 2;
344
345 ret = clk_set_rate(i2s->clk_i2s_sync, i2sclock);
346 if (ret) {
347 dev_err(dev, "Can't set I2S sync clock rate\n");
348 return ret;
349 }
350
351 ret = clk_set_rate(i2s->clk_audio_2x, i2sclock);
352 if (ret) {
353 dev_err(dev, "Can't set I2S sync clock rate\n");
354 return ret;
355 }
356
357 ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_2x);
358 if (ret) {
359 dev_err(dev, "Can't set parent of audio2x clock\n");
360 return ret;
361 }
362
363 tegra30_i2s_enable_clocks(i2s);
364 }
365
366 i2s_client_ch = (i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) ?
367 params_channels(params) : 2;
368
369 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
370 ((params_channels(params) - 1) <<
371 TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
372 ((i2s_client_ch - 1) <<
373 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
374 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
375 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
376
377 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
378 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
379 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
380
381 tegra30_ahub_set_tx_cif_channels(i2s->txcif,
382 params_channels(params),
383 params_channels(params));
384 } else {
385 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
386 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
387
388 tegra30_ahub_set_rx_cif_channels(i2s->rxcif,
389 params_channels(params),
390 params_channels(params));
391 }
392
393 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
394 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
395 tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
396
397 tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
398
399 val = tegra30_i2s_read(i2s, TEGRA30_I2S_SLOT_CTRL);
400 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
401 val &= ~TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK;
402 val |= (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
403 } else {
404 val &= ~TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK;
405 val |= (1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
406 }
407 tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL, val);
408
409 tegra30_i2s_disable_clocks(i2s);
410
411 return 0;
412}
413
414static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
415{
416 tegra30_ahub_enable_tx_fifo(i2s->txcif);
417 /* if this is the only user of i2s tx then enable it*/
418 if (i2s->playback_ref_count == 1) {
419 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
420 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
421 }
422}
423
424static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
425{
426 tegra30_ahub_disable_tx_fifo(i2s->txcif);
427 /* if this is the only user of i2s tx then disable it*/
428 if (i2s->playback_ref_count == 1) {
429 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
430 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
431 }
432}
433
434static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
435{
436 tegra30_ahub_enable_rx_fifo(i2s->rxcif);
437 if (!i2s->is_call_mode_rec) {
438 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
439 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
440 }
441}
442
443static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
444{
445 tegra30_ahub_disable_rx_fifo(i2s->rxcif);
446 if (!i2s->is_call_mode_rec) {
447 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
448 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
449 }
450}
451
452static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
453 struct snd_soc_dai *dai)
454{
455 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
456
457 switch (cmd) {
458 case SNDRV_PCM_TRIGGER_START:
459 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
460 case SNDRV_PCM_TRIGGER_RESUME:
461 tegra30_i2s_enable_clocks(i2s);
462 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
463 tegra30_i2s_start_playback(i2s);
464 else
465 tegra30_i2s_start_capture(i2s);
466 break;
467 case SNDRV_PCM_TRIGGER_STOP:
468 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
469 case SNDRV_PCM_TRIGGER_SUSPEND:
470 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
471 tegra30_i2s_stop_playback(i2s);
472 else
473 tegra30_i2s_stop_capture(i2s);
474 tegra30_i2s_disable_clocks(i2s);
475 break;
476 default:
477 return -EINVAL;
478 }
479
480 return 0;
481}
482
483static int tegra30_i2s_probe(struct snd_soc_dai *dai)
484{
485 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
486#ifdef CONFIG_PM
487 int i;
488#endif
489
490 dai->capture_dma_data = &i2s->capture_dma_data;
491 dai->playback_dma_data = &i2s->playback_dma_data;
492
493#ifdef CONFIG_PM
494 tegra30_i2s_enable_clocks(i2s);
495
496 /*cache the POR values of i2s regs*/
497 for (i = 0; i < ((TEGRA30_I2S_CIF_TX_CTRL>>2) + 1); i++)
498 i2s->reg_cache[i] = tegra30_i2s_read(i2s, i<<2);
499
500 tegra30_i2s_disable_clocks(i2s);
501#endif
502
503 return 0;
504}
505
506#ifdef CONFIG_PM
507int tegra30_i2s_resume(struct snd_soc_dai *cpu_dai)
508{
509 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
510 int i, ret = 0;
511
512 tegra30_i2s_enable_clocks(i2s);
513
514 /*restore the i2s regs*/
515 for (i = 0; i < ((TEGRA30_I2S_CIF_TX_CTRL>>2) + 1); i++)
516 tegra30_i2s_write(i2s, i<<2, i2s->reg_cache[i]);
517
518 tegra30_ahub_apbif_resume();
519
520 tegra30_i2s_disable_clocks(i2s);
521
522 if (i2s->dam_ch_refcount)
523 ret = tegra30_dam_resume(i2s->dam_ifc);
524
525 return ret;
526}
527#else
528#define tegra30_i2s_resume NULL
529#endif
530
531static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
532 .startup = tegra30_i2s_startup,
533 .shutdown = tegra30_i2s_shutdown,
534 .set_fmt = tegra30_i2s_set_fmt,
535 .hw_params = tegra30_i2s_hw_params,
536 .trigger = tegra30_i2s_trigger,
537};
538
539#define TEGRA30_I2S_DAI(id) \
540 { \
541 .name = DRV_NAME "." #id, \
542 .probe = tegra30_i2s_probe, \
543 .resume = tegra30_i2s_resume, \
544 .playback = { \
545 .channels_min = 1, \
546 .channels_max = 2, \
547 .rates = SNDRV_PCM_RATE_8000_96000, \
548 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
549 }, \
550 .capture = { \
551 .channels_min = 1, \
552 .channels_max = 2, \
553 .rates = SNDRV_PCM_RATE_8000_96000, \
554 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
555 }, \
556 .ops = &tegra30_i2s_dai_ops, \
557 .symmetric_rates = 1, \
558 }
559
560struct snd_soc_dai_driver tegra30_i2s_dai[] = {
561 TEGRA30_I2S_DAI(0),
562 TEGRA30_I2S_DAI(1),
563 TEGRA30_I2S_DAI(2),
564 TEGRA30_I2S_DAI(3),
565 TEGRA30_I2S_DAI(4),
566};
567
568static int configure_baseband_i2s(struct tegra30_i2s *i2s, int is_i2smaster,
569 int is_formatdsp, int channels, int rate, int bitsize)
570{
571 u32 val;
572 int i2sclock, bitcnt;
573
574 i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
575 TEGRA30_I2S_CTRL_LRCK_MASK |
576 TEGRA30_I2S_CTRL_MASTER_ENABLE);
577 i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK;
578
579 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
580
581 if (is_i2smaster)
582 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
583
584 if (is_formatdsp) {
585 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
586 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
587 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE;
588 } else {
589 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
590 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
591 i2s->reg_ch_ctrl |= TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE;
592 }
593
594 tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
595
596 val = tegra30_i2s_read(i2s, TEGRA30_I2S_SLOT_CTRL);
597 val &= ~(TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK |
598 TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK);
599 val |= (1 << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT |
600 1 << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
601 tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL, val);
602
603 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
604 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
605 tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
606
607 i2sclock = rate * channels * bitsize * 2;
608
609 /* additional 8 for baseband */
610 if (is_formatdsp)
611 i2sclock *= 8;
612
613 clk_set_rate(i2s->clk_i2s, i2sclock);
614
615 if (is_formatdsp) {
616 bitcnt = (i2sclock/rate) - 1;
617 val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
618 if (i2sclock % (rate))
619 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
620 } else {
621 bitcnt = (i2sclock/(2*rate)) - 1;
622 val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
623 if (i2sclock % (2*rate))
624 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
625 }
626
627 tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
628
629 /* configure the i2s cif*/
630 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
631 ((channels - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
632 ((channels - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
633 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
634 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
635 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
636 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
637
638 val &= ~TEGRA30_AUDIOCIF_CTRL_DIRECTION_MASK;
639 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
640 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
641
642 return 0;
643}
644
645static int configure_dam(struct tegra30_i2s *i2s, int out_channel,
646 int out_rate, int out_bitsize, int in_channels,
647 int in_rate, int in_bitsize)
648{
649
650 if (!i2s->dam_ch_refcount)
651 i2s->dam_ifc = tegra30_dam_allocate_controller();
652
653 tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC);
654 i2s->dam_ch_refcount++;
655 tegra30_dam_enable_clock(i2s->dam_ifc);
656 tegra30_dam_set_samplerate(i2s->dam_ifc, TEGRA30_DAM_CHOUT, out_rate);
657 tegra30_dam_set_samplerate(i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC,
658 in_rate);
659 tegra30_dam_set_gain(i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC, 0x1000);
660 tegra30_dam_set_acif(i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC,
661 in_channels, in_bitsize, 1, 16);
662 tegra30_dam_set_acif(i2s->dam_ifc, TEGRA30_DAM_CHOUT,
663 out_channel, out_bitsize, out_channel, out_bitsize);
664
665 return 0;
666}
667
668
669int tegra30_make_voice_call_connections(struct codec_config *codec_info,
670 struct codec_config *bb_info)
671{
672 struct tegra30_i2s *codec_i2s;
673 struct tegra30_i2s *bb_i2s;
674
675 codec_i2s = &i2scont[codec_info->i2s_id];
676 bb_i2s = &i2scont[bb_info->i2s_id];
677 tegra30_i2s_enable_clocks(codec_i2s);
678 tegra30_i2s_enable_clocks(bb_i2s);
679
680 /* increment the codec i2s playback ref count */
681 codec_i2s->playback_ref_count++;
682 bb_i2s->playback_ref_count++;
683
684 /*Configure codec i2s*/
685 configure_baseband_i2s(codec_i2s, codec_info->is_i2smaster,
686 codec_info->is_format_dsp, codec_info->channels,
687 codec_info->rate, codec_info->bitsize);
688
689 /*Configure bb i2s*/
690 configure_baseband_i2s(bb_i2s, bb_info->is_i2smaster,
691 bb_info->is_format_dsp, bb_info->channels,
692 bb_info->rate, bb_info->bitsize);
693
694 /*configure codec dam*/
695 configure_dam(codec_i2s, codec_info->channels,
696 codec_info->rate, codec_info->bitsize, bb_info->channels,
697 bb_info->rate, bb_info->bitsize);
698
699 /*configure bb dam*/
700 configure_dam(bb_i2s, bb_info->channels,
701 bb_info->rate, bb_info->bitsize, codec_info->channels,
702 codec_info->rate, codec_info->bitsize);
703
704 /*make ahub connections*/
705
706 /* if this is the only user of i2s tx then make ahub i2s rx connection*/
707 if (codec_i2s->playback_ref_count == 1) {
708 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
709 codec_info->i2s_id, TEGRA30_AHUB_TXCIF_DAM0_TX0 +
710 codec_i2s->dam_ifc);
711 }
712
713 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
714 bb_info->i2s_id, TEGRA30_AHUB_TXCIF_DAM0_TX0 +
715 bb_i2s->dam_ifc);
716 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
717 (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
718 bb_info->i2s_id);
719 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
720 (bb_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
721 codec_info->i2s_id);
722
723 /*enable dam and i2s*/
724 tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
725 TEGRA30_DAM_CHIN0_SRC);
726 tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
727 TEGRA30_DAM_CHIN0_SRC);
728
729 /* if this is the only user of i2s tx then enable it*/
730 if (codec_i2s->playback_ref_count == 1)
731 codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
732
733 codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
734 tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
735 codec_i2s->reg_ctrl);
736 bb_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
737 bb_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
738 tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL,
739 bb_i2s->reg_ctrl);
740
741 return 0;
742}
743
744int tegra30_break_voice_call_connections(struct codec_config *codec_info,
745 struct codec_config *bb_info)
746{
747 struct tegra30_i2s *codec_i2s;
748 struct tegra30_i2s *bb_i2s;
749
750 codec_i2s = &i2scont[codec_info->i2s_id];
751 bb_i2s = &i2scont[bb_info->i2s_id];
752
753 /* disconnect the ahub connections */
754
755 /* if this is the only user of i2s tx then break ahub
756 i2s rx connection */
757 if (codec_i2s->playback_ref_count == 1)
758 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
759 + codec_info->i2s_id);
760
761 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
762 + bb_info->i2s_id);
763 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
764 + (codec_i2s->dam_ifc*2));
765 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
766 + (bb_i2s->dam_ifc*2));
767
768 /* disable the i2s */
769
770 /* if this is the only user of i2s tx then disable it*/
771 if (codec_i2s->playback_ref_count == 1)
772 codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
773
774 codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
775 tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
776 bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
777 bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
778 tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL, bb_i2s->reg_ctrl);
779 tegra30_i2s_disable_clocks(codec_i2s);
780 tegra30_i2s_disable_clocks(bb_i2s);
781
782 /* decrement the codec i2s playback ref count */
783 codec_i2s->playback_ref_count--;
784 bb_i2s->playback_ref_count--;
785
786 /* disable the codec dam */
787 tegra30_dam_enable(codec_i2s->dam_ifc,
788 TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
789 tegra30_dam_disable_clock(codec_i2s->dam_ifc);
790 tegra30_dam_free_channel(codec_i2s->dam_ifc,
791 TEGRA30_DAM_CHIN0_SRC);
792 codec_i2s->dam_ch_refcount--;
793 if (!codec_i2s->dam_ch_refcount)
794 tegra30_dam_free_controller(codec_i2s->dam_ifc);
795
796 /* disable the bb dam */
797 tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
798 TEGRA30_DAM_CHIN0_SRC);
799 tegra30_dam_disable_clock(bb_i2s->dam_ifc);
800 tegra30_dam_free_channel(bb_i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC);
801 bb_i2s->dam_ch_refcount--;
802 if (!bb_i2s->dam_ch_refcount)
803 tegra30_dam_free_controller(bb_i2s->dam_ifc);
804
805 return 0;
806}
807
808static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
809{
810 struct tegra30_i2s *i2s;
811 struct resource *mem, *memregion;
812 int ret;
813
814 if ((pdev->id < 0) ||
815 (pdev->id >= ARRAY_SIZE(tegra30_i2s_dai))) {
816 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
817 return -EINVAL;
818 }
819
820 i2s = &i2scont[pdev->id];
821 dev_set_drvdata(&pdev->dev, i2s);
822 i2s->id = pdev->id;
823
824 i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
825 if (IS_ERR(i2s->clk_i2s)) {
826 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
827 ret = PTR_ERR(i2s->clk_i2s);
828 goto exit;
829 }
830
831 i2s->clk_i2s_sync = clk_get(&pdev->dev, "ext_audio_sync");
832 if (IS_ERR(i2s->clk_i2s_sync)) {
833 dev_err(&pdev->dev, "Can't retrieve i2s_sync clock\n");
834 ret = PTR_ERR(i2s->clk_i2s_sync);
835 goto err_i2s_clk_put;
836 }
837
838 i2s->clk_audio_2x = clk_get(&pdev->dev, "audio_sync_2x");
839 if (IS_ERR(i2s->clk_audio_2x)) {
840 dev_err(&pdev->dev, "Can't retrieve audio 2x clock\n");
841 ret = PTR_ERR(i2s->clk_audio_2x);
842 goto err_i2s_sync_clk_put;
843 }
844
845 i2s->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
846 if (IS_ERR(i2s->clk_pll_a_out0)) {
847 dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
848 ret = PTR_ERR(i2s->clk_pll_a_out0);
849 goto err_audio_2x_clk_put;
850 }
851
852 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
853 if (!mem) {
854 dev_err(&pdev->dev, "No memory resource\n");
855 ret = -ENODEV;
856 goto err_pll_a_out0_clk_put;
857 }
858
859 memregion = request_mem_region(mem->start, resource_size(mem),
860 DRV_NAME);
861 if (!memregion) {
862 dev_err(&pdev->dev, "Memory region already claimed\n");
863 ret = -EBUSY;
864 goto err_pll_a_out0_clk_put;
865 }
866
867 i2s->regs = ioremap(mem->start, resource_size(mem));
868 if (!i2s->regs) {
869 dev_err(&pdev->dev, "ioremap failed\n");
870 ret = -ENOMEM;
871 goto err_release;
872 }
873
874 ret = snd_soc_register_dai(&pdev->dev, &tegra30_i2s_dai[pdev->id]);
875 if (ret) {
876 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
877 ret = -ENOMEM;
878 goto err_unmap;
879 }
880
881 tegra30_i2s_debug_add(i2s, pdev->id);
882
883 return 0;
884
885err_unmap:
886 iounmap(i2s->regs);
887err_release:
888 release_mem_region(mem->start, resource_size(mem));
889err_pll_a_out0_clk_put:
890 clk_put(i2s->clk_pll_a_out0);
891err_audio_2x_clk_put:
892 clk_put(i2s->clk_audio_2x);
893err_i2s_sync_clk_put:
894 clk_put(i2s->clk_i2s_sync);
895err_i2s_clk_put:
896 clk_put(i2s->clk_i2s);
897exit:
898 return ret;
899}
900
901static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
902{
903 struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
904 struct resource *res;
905
906 snd_soc_unregister_dai(&pdev->dev);
907
908 tegra30_i2s_debug_remove(i2s);
909
910 iounmap(i2s->regs);
911
912 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
913 release_mem_region(res->start, resource_size(res));
914
915 clk_put(i2s->clk_pll_a_out0);
916 clk_put(i2s->clk_audio_2x);
917 clk_put(i2s->clk_i2s_sync);
918 clk_put(i2s->clk_i2s);
919
920 kfree(i2s);
921
922 return 0;
923}
924
925static struct platform_driver tegra30_i2s_driver = {
926 .driver = {
927 .name = DRV_NAME,
928 .owner = THIS_MODULE,
929 },
930 .probe = tegra30_i2s_platform_probe,
931 .remove = __devexit_p(tegra30_i2s_platform_remove),
932};
933
934static int __init snd_tegra30_i2s_init(void)
935{
936 return platform_driver_register(&tegra30_i2s_driver);
937}
938module_init(snd_tegra30_i2s_init);
939
940static void __exit snd_tegra30_i2s_exit(void)
941{
942 platform_driver_unregister(&tegra30_i2s_driver);
943}
944module_exit(snd_tegra30_i2s_exit);
945
946MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
947MODULE_DESCRIPTION("Tegra 30 I2S ASoC driver");
948MODULE_LICENSE("GPL");
949MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
new file mode 100644
index 00000000000..b9baddd5db8
--- /dev/null
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -0,0 +1,274 @@
1/*
2 * tegra30_i2s.h - Definitions for Tegra 30 I2S driver
3 *
4 * Copyright (c) 2010-2011, NVIDIA Corporation.
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#ifndef __TEGRA30_I2S_H__
23#define __TEGRA30_I2S_H__
24
25#include "tegra_pcm.h"
26
27/* Register offsets from TEGRA30_I2S*_BASE */
28
29#define TEGRA30_I2S_CTRL 0x0
30#define TEGRA30_I2S_TIMING 0x4
31#define TEGRA30_I2S_OFFSET 0x08
32#define TEGRA30_I2S_CH_CTRL 0x0c
33#define TEGRA30_I2S_SLOT_CTRL 0x10
34#define TEGRA30_I2S_CIF_RX_CTRL 0x14
35#define TEGRA30_I2S_CIF_TX_CTRL 0x18
36#define TEGRA30_I2S_FLOWCTL 0x1c
37#define TEGRA30_I2S_TX_STEP 0x20
38#define TEGRA30_I2S_FLOW_STATUS 0x24
39#define TEGRA30_I2S_FLOW_TOTAL 0x28
40#define TEGRA30_I2S_FLOW_OVER 0x2c
41#define TEGRA30_I2S_FLOW_UNDER 0x30
42#define TEGRA30_I2S_LCOEF_1_4_0 0x34
43#define TEGRA30_I2S_LCOEF_1_4_1 0x38
44#define TEGRA30_I2S_LCOEF_1_4_2 0x3c
45#define TEGRA30_I2S_LCOEF_1_4_3 0x40
46#define TEGRA30_I2S_LCOEF_1_4_4 0x44
47#define TEGRA30_I2S_LCOEF_1_4_5 0x48
48#define TEGRA30_I2S_LCOEF_2_4_0 0x4c
49#define TEGRA30_I2S_LCOEF_2_4_1 0x50
50#define TEGRA30_I2S_LCOEF_2_4_2 0x54
51
52/* Fields in TEGRA30_I2S_CTRL */
53
54#define TEGRA30_I2S_CTRL_XFER_EN_TX (1 << 31)
55#define TEGRA30_I2S_CTRL_XFER_EN_RX (1 << 30)
56#define TEGRA30_I2S_CTRL_CG_EN (1 << 29)
57#define TEGRA30_I2S_CTRL_SOFT_RESET (1 << 28)
58#define TEGRA30_I2S_CTRL_TX_FLOWCTL_EN (1 << 27)
59
60#define TEGRA30_I2S_CTRL_OBS_SEL_SHIFT 24
61#define TEGRA30_I2S_CTRL_OBS_SEL_MASK (7 << TEGRA30_I2S_CTRL_OBS_SEL_SHIFT)
62
63#define TEGRA30_I2S_FRAME_FORMAT_LRCK 0
64#define TEGRA30_I2S_FRAME_FORMAT_FSYNC 1
65
66#define TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT 12
67#define TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK (7 << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
68#define TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK (TEGRA30_I2S_FRAME_FORMAT_LRCK << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
69#define TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC (TEGRA30_I2S_FRAME_FORMAT_FSYNC << TEGRA30_I2S_CTRL_FRAME_FORMAT_SHIFT)
70
71#define TEGRA30_I2S_CTRL_MASTER_ENABLE (1 << 10)
72
73#define TEGRA30_I2S_LRCK_LEFT_LOW 0
74#define TEGRA30_I2S_LRCK_RIGHT_LOW 1
75
76#define TEGRA30_I2S_CTRL_LRCK_SHIFT 9
77#define TEGRA30_I2S_CTRL_LRCK_MASK (1 << TEGRA30_I2S_CTRL_LRCK_SHIFT)
78#define TEGRA30_I2S_CTRL_LRCK_L_LOW (TEGRA30_I2S_LRCK_LEFT_LOW << TEGRA30_I2S_CTRL_LRCK_SHIFT)
79#define TEGRA30_I2S_CTRL_LRCK_R_LOW (TEGRA30_I2S_LRCK_RIGHT_LOW << TEGRA30_I2S_CTRL_LRCK_SHIFT)
80
81#define TEGRA30_I2S_CTRL_LPBK_ENABLE (1 << 8)
82
83#define TEGRA30_I2S_BIT_CODE_LINEAR 0
84#define TEGRA30_I2S_BIT_CODE_ULAW 1
85#define TEGRA30_I2S_BIT_CODE_ALAW 2
86
87#define TEGRA30_I2S_CTRL_BIT_CODE_SHIFT 4
88#define TEGRA30_I2S_CTRL_BIT_CODE_MASK (3 << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
89#define TEGRA30_I2S_CTRL_BIT_CODE_LINEAR (TEGRA30_I2S_BIT_CODE_LINEAR << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
90#define TEGRA30_I2S_CTRL_BIT_CODE_ULAW (TEGRA30_I2S_BIT_CODE_ULAW << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
91#define TEGRA30_I2S_CTRL_BIT_CODE_ALAW (TEGRA30_I2S_BIT_CODE_ALAW << TEGRA30_I2S_CTRL_BIT_CODE_SHIFT)
92
93#define TEGRA30_I2S_BITS_8 1
94#define TEGRA30_I2S_BITS_12 2
95#define TEGRA30_I2S_BITS_16 3
96#define TEGRA30_I2S_BITS_20 4
97#define TEGRA30_I2S_BITS_24 5
98#define TEGRA30_I2S_BITS_28 6
99#define TEGRA30_I2S_BITS_32 7
100
101/* Sample container size; see {RX,TX}_MASK field in CH_CTRL below */
102#define TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT 0
103#define TEGRA30_I2S_CTRL_BIT_SIZE_MASK (7 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
104#define TEGRA30_I2S_CTRL_BIT_SIZE_8 (TEGRA30_I2S_BITS_8 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
105#define TEGRA30_I2S_CTRL_BIT_SIZE_12 (TEGRA30_I2S_BITS_12 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
106#define TEGRA30_I2S_CTRL_BIT_SIZE_16 (TEGRA30_I2S_BITS_16 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
107#define TEGRA30_I2S_CTRL_BIT_SIZE_20 (TEGRA30_I2S_BITS_20 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
108#define TEGRA30_I2S_CTRL_BIT_SIZE_24 (TEGRA30_I2S_BITS_24 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
109#define TEGRA30_I2S_CTRL_BIT_SIZE_28 (TEGRA30_I2S_BITS_28 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
110#define TEGRA30_I2S_CTRL_BIT_SIZE_32 (TEGRA30_I2S_BITS_32 << TEGRA30_I2S_CTRL_BIT_SIZE_SHIFT)
111
112/* Fields in TEGRA30_I2S_TIMING */
113
114#define TEGRA30_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
115#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
116#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
117#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
118
119/* Fields in TEGRA30_I2S_OFFSET */
120
121#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT 16
122#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK_US 0x7ff
123#define TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK (TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_MASK_US << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT)
124#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT 0
125#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK_US 0x7ff
126#define TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK (TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_MASK_US << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT)
127
128/* Fields in TEGRA30_I2S_CH_CTRL */
129
130/* (FSYNC width - 1) in bit clocks */
131#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT 24
132#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK_US 0xff
133#define TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK (TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK_US << TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT)
134
135#define TEGRA30_I2S_HIGHZ_NO 0
136#define TEGRA30_I2S_HIGHZ_YES 1
137#define TEGRA30_I2S_HIGHZ_ON_HALF_BIT_CLK 2
138
139#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT 12
140#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_MASK (3 << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
141#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_NO (TEGRA30_I2S_HIGHZ_NO << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
142#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_YES (TEGRA30_I2S_HIGHZ_YES << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
143#define TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_ON_HALF_BIT_CLK (TEGRA30_I2S_HIGHZ_ON_HALF_BIT_CLK << TEGRA30_I2S_CH_CTRL_HIGHZ_CTRL_SHIFT)
144
145#define TEGRA30_I2S_MSB_FIRST 0
146#define TEGRA30_I2S_LSB_FIRST 1
147
148#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT 10
149#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_MASK (1 << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
150#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_MSB_FIRST (TEGRA30_I2S_MSB_FIRST << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
151#define TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_LSB_FIRST (TEGRA30_I2S_LSB_FIRST << TEGRA30_I2S_CH_CTRL_RX_BIT_ORDER_SHIFT)
152#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT 9
153#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_MASK (1 << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
154#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_MSB_FIRST (TEGRA30_I2S_MSB_FIRST << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
155#define TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_LSB_FIRST (TEGRA30_I2S_LSB_FIRST << TEGRA30_I2S_CH_CTRL_TX_BIT_ORDER_SHIFT)
156
157#define TEGRA30_I2S_POS_EDGE 0
158#define TEGRA30_I2S_NEG_EDGE 1
159
160#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT 8
161#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_MASK (1 << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
162#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_POS_EDGE (TEGRA30_I2S_POS_EDGE << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
163#define TEGRA30_I2S_CH_CTRL_EGDE_CTRL_NEG_EDGE (TEGRA30_I2S_NEG_EDGE << TEGRA30_I2S_CH_CTRL_EGDE_CTRL_SHIFT)
164
165/* Sample size is # bits from BIT_SIZE minus this field */
166#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_SHIFT 4
167#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK_US 7
168#define TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK (TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_MASK_US << TEGRA30_I2S_CH_CTRL_RX_MASK_BITS_SHIFT)
169
170#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_SHIFT 0
171#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK_US 7
172#define TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK (TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_MASK_US << TEGRA30_I2S_CH_CTRL_TX_MASK_BITS_SHIFT)
173
174/* Fields in TEGRA30_I2S_SLOT_CTRL */
175
176/* Number of slots in frame, minus 1 */
177#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT 16
178#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US 7
179#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK (TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT)
180
181/* TDM mode slot enable bitmask */
182#define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT 8
183#define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK (0xff << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT)
184
185#define TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT 0
186#define TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK (0xff << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT)
187
188/* Fields in TEGRA30_I2S_CIF_RX_CTRL */
189/* Uses field from TEGRA30_AUDIOCIF_CTRL_* in tegra30_ahub.h */
190
191/* Fields in TEGRA30_I2S_CIF_TX_CTRL */
192/* Uses field from TEGRA30_AUDIOCIF_CTRL_* in tegra30_ahub.h */
193
194/* Fields in TEGRA30_I2S_FLOWCTL */
195
196#define TEGRA30_I2S_FILTER_LINEAR 0
197#define TEGRA30_I2S_FILTER_QUAD 1
198
199#define TEGRA30_I2S_FLOWCTL_FILTER_SHIFT 31
200#define TEGRA30_I2S_FLOWCTL_FILTER_MASK (1 << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
201#define TEGRA30_I2S_FLOWCTL_FILTER_LINEAR (TEGRA30_I2S_FILTER_LINEAR << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
202#define TEGRA30_I2S_FLOWCTL_FILTER_QUAD (TEGRA30_I2S_FILTER_QUAD << TEGRA30_I2S_FLOWCTL_FILTER_SHIFT)
203
204/* Fields in TEGRA30_I2S_TX_STEP */
205
206#define TEGRA30_I2S_TX_STEP_SHIFT 0
207#define TEGRA30_I2S_TX_STEP_MASK_US 0xffff
208#define TEGRA30_I2S_TX_STEP_MASK (TEGRA30_I2S_TX_STEP_MASK_US << TEGRA30_I2S_TX_STEP_SHIFT)
209
210/* Fields in TEGRA30_I2S_FLOW_STATUS */
211
212#define TEGRA30_I2S_FLOW_STATUS_UNDERFLOW (1 << 31)
213#define TEGRA30_I2S_FLOW_STATUS_OVERFLOW (1 << 30)
214#define TEGRA30_I2S_FLOW_STATUS_MONITOR_INT_EN (1 << 4)
215#define TEGRA30_I2S_FLOW_STATUS_COUNTER_CLR (1 << 3)
216#define TEGRA30_I2S_FLOW_STATUS_MONITOR_CLR (1 << 2)
217#define TEGRA30_I2S_FLOW_STATUS_COUNTER_EN (1 << 1)
218#define TEGRA30_I2S_FLOW_STATUS_MONITOR_EN (1 << 0)
219
220/*
221 * There are no fields in TEGRA30_I2S_FLOW_TOTAL, TEGRA30_I2S_FLOW_OVER,
222 * TEGRA30_I2S_FLOW_UNDER; they are counters taking the whole register.
223 */
224
225/* Fields in TEGRA30_I2S_LCOEF_* */
226
227#define TEGRA30_I2S_LCOEF_COEF_SHIFT 0
228#define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff
229#define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT)
230
231/* Number of i2s controllers*/
232#define TEGRA30_NR_I2S_IFC 5
233
234struct tegra30_i2s {
235 int id;
236 struct clk *clk_i2s;
237 struct clk *clk_i2s_sync;
238 struct clk *clk_audio_2x;
239 struct clk *clk_pll_a_out0;
240 enum tegra30_ahub_rxcif rxcif;
241 struct tegra_pcm_dma_params capture_dma_data;
242 enum tegra30_ahub_txcif txcif;
243 struct tegra_pcm_dma_params playback_dma_data;
244 void __iomem *regs;
245 struct dentry *debug;
246 u32 reg_ctrl;
247 u32 reg_ch_ctrl;
248 int dam_ifc;
249 int dam_ch_refcount;
250 int playback_ref_count;
251 bool is_dam_used;
252#ifdef CONFIG_PM
253 u32 reg_cache[(TEGRA30_I2S_CIF_TX_CTRL >> 2) + 1];
254#endif
255 int call_record_dam_ifc;
256 int is_call_mode_rec;
257};
258
259struct codec_config {
260 int i2s_id;
261 int rate;
262 int channels;
263 int bitsize;
264 int is_i2smaster;
265 int is_format_dsp;
266};
267
268int tegra30_make_voice_call_connections(struct codec_config *codec_info,
269 struct codec_config *bb_info);
270
271int tegra30_break_voice_call_connections(struct codec_config *codec_info,
272 struct codec_config *bb_info);
273
274#endif
diff --git a/sound/soc/tegra/tegra30_spdif.c b/sound/soc/tegra/tegra30_spdif.c
new file mode 100644
index 00000000000..038127c0afb
--- /dev/null
+++ b/sound/soc/tegra/tegra30_spdif.c
@@ -0,0 +1,505 @@
1/*
2 * tegra30_spdif.c - Tegra30 SPDIF driver
3 *
4 * Author: Sumit Bhattacharya <sumitb@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2011, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <linux/clk.h>
32#include <linux/module.h>
33#include <linux/debugfs.h>
34#include <linux/device.h>
35#include <linux/platform_device.h>
36#include <linux/seq_file.h>
37#include <linux/slab.h>
38#include <linux/io.h>
39#include <mach/iomap.h>
40#include <mach/hdmi-audio.h>
41#include <sound/core.h>
42#include <sound/pcm.h>
43#include <sound/pcm_params.h>
44#include <sound/soc.h>
45
46#include "tegra30_spdif.h"
47
48#define DRV_NAME "tegra30-spdif"
49
50static inline void tegra30_spdif_write(struct tegra30_spdif *spdif,
51 u32 reg, u32 val)
52{
53 __raw_writel(val, spdif->regs + reg);
54}
55
56static inline u32 tegra30_spdif_read(struct tegra30_spdif *spdif, u32 reg)
57{
58 return __raw_readl(spdif->regs + reg);
59}
60
61static void tegra30_spdif_enable_clocks(struct tegra30_spdif *spdif)
62{
63 clk_enable(spdif->clk_spdif_out);
64 tegra30_ahub_enable_clocks();
65}
66
67static void tegra30_spdif_disable_clocks(struct tegra30_spdif *spdif)
68{
69 tegra30_ahub_disable_clocks();
70 clk_disable(spdif->clk_spdif_out);
71}
72
73#ifdef CONFIG_DEBUG_FS
74static int tegra30_spdif_show(struct seq_file *s, void *unused)
75{
76#define REG(r) { r, #r }
77 static const struct {
78 int offset;
79 const char *name;
80 } regs[] = {
81 REG(TEGRA30_SPDIF_CTRL),
82 REG(TEGRA30_SPDIF_STROBE_CTRL),
83 REG(TEGRA30_SPDIF_CIF_TXD_CTRL),
84 REG(TEGRA30_SPDIF_CIF_RXD_CTRL),
85 REG(TEGRA30_SPDIF_CIF_TXU_CTRL),
86 REG(TEGRA30_SPDIF_CIF_RXU_CTRL),
87 REG(TEGRA30_SPDIF_CH_STA_RX_A),
88 REG(TEGRA30_SPDIF_CH_STA_RX_B),
89 REG(TEGRA30_SPDIF_CH_STA_RX_C),
90 REG(TEGRA30_SPDIF_CH_STA_RX_D),
91 REG(TEGRA30_SPDIF_CH_STA_RX_E),
92 REG(TEGRA30_SPDIF_CH_STA_RX_F),
93 REG(TEGRA30_SPDIF_CH_STA_TX_A),
94 REG(TEGRA30_SPDIF_CH_STA_TX_B),
95 REG(TEGRA30_SPDIF_CH_STA_TX_C),
96 REG(TEGRA30_SPDIF_CH_STA_TX_D),
97 REG(TEGRA30_SPDIF_CH_STA_TX_E),
98 REG(TEGRA30_SPDIF_CH_STA_TX_F),
99 REG(TEGRA30_SPDIF_FLOWCTL_CTRL),
100 REG(TEGRA30_SPDIF_TX_STEP),
101 REG(TEGRA30_SPDIF_FLOW_STATUS),
102 REG(TEGRA30_SPDIF_FLOW_TOTAL),
103 REG(TEGRA30_SPDIF_FLOW_OVER),
104 REG(TEGRA30_SPDIF_FLOW_UNDER),
105 REG(TEGRA30_SPDIF_LCOEF_1_4_0),
106 REG(TEGRA30_SPDIF_LCOEF_1_4_1),
107 REG(TEGRA30_SPDIF_LCOEF_1_4_2),
108 REG(TEGRA30_SPDIF_LCOEF_1_4_3),
109 REG(TEGRA30_SPDIF_LCOEF_1_4_4),
110 REG(TEGRA30_SPDIF_LCOEF_1_4_5),
111 REG(TEGRA30_SPDIF_LCOEF_2_4_0),
112 REG(TEGRA30_SPDIF_LCOEF_2_4_1),
113 REG(TEGRA30_SPDIF_LCOEF_2_4_2),
114 };
115#undef REG
116
117 struct tegra30_spdif *spdif = s->private;
118 int i;
119
120 tegra30_spdif_enable_clocks(spdif);
121
122 for (i = 0; i < ARRAY_SIZE(regs); i++) {
123 u32 val = tegra30_spdif_read(spdif, regs[i].offset);
124 seq_printf(s, "%s = %08x\n", regs[i].name, val);
125 }
126
127 tegra30_spdif_disable_clocks(spdif);
128
129 return 0;
130}
131
132static int tegra30_spdif_debug_open(struct inode *inode, struct file *file)
133{
134 return single_open(file, tegra30_spdif_show, inode->i_private);
135}
136
137static const struct file_operations tegra30_spdif_debug_fops = {
138 .open = tegra30_spdif_debug_open,
139 .read = seq_read,
140 .llseek = seq_lseek,
141 .release = single_release,
142};
143
144static void tegra30_spdif_debug_add(struct tegra30_spdif *spdif)
145{
146 char name[] = DRV_NAME;
147
148 spdif->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
149 spdif, &tegra30_spdif_debug_fops);
150}
151
152static void tegra30_spdif_debug_remove(struct tegra30_spdif *spdif)
153{
154 if (spdif->debug)
155 debugfs_remove(spdif->debug);
156}
157#else
158static inline void tegra30_spdif_debug_add(struct tegra30_spdif *spdif)
159{
160}
161
162static inline void tegra30_spdif_debug_remove(struct tegra30_spdif *spdif)
163{
164}
165#endif
166
167int tegra30_spdif_startup(struct snd_pcm_substream *substream,
168 struct snd_soc_dai *dai)
169{
170 struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
171 int ret = 0;
172
173 tegra30_spdif_enable_clocks(spdif);
174
175 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
176 ret = tegra30_ahub_allocate_tx_fifo(&spdif->txcif,
177 &spdif->playback_dma_data.addr,
178 &spdif->playback_dma_data.req_sel);
179 spdif->playback_dma_data.wrap = 4;
180 spdif->playback_dma_data.width = 32;
181 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_SPDIF_RX0,
182 spdif->txcif);
183 }
184
185 tegra30_spdif_disable_clocks(spdif);
186
187 return ret;
188}
189
190void tegra30_spdif_shutdown(struct snd_pcm_substream *substream,
191 struct snd_soc_dai *dai)
192{
193 struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
194
195 tegra30_spdif_enable_clocks(spdif);
196
197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
198 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_SPDIF_RX0);
199 tegra30_ahub_free_tx_fifo(spdif->txcif);
200 }
201
202 tegra30_spdif_disable_clocks(spdif);
203}
204
205static int tegra30_spdif_hw_params(struct snd_pcm_substream *substream,
206 struct snd_pcm_hw_params *params,
207 struct snd_soc_dai *dai)
208{
209 struct device *dev = substream->pcm->card->dev;
210 struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
211 int ret, srate, spdifclock;
212
213 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
214 dev_err(dev, "spdif capture is not supported\n");
215 return -EINVAL;
216 }
217
218 spdif->reg_ctrl &= ~TEGRA30_SPDIF_CTRL_BIT_MODE_MASK;
219 switch (params_format(params)) {
220 case SNDRV_PCM_FORMAT_S16_LE:
221 spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_PACK_ENABLE;
222 spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_BIT_MODE_16BIT;
223 break;
224 default:
225 return -EINVAL;
226 }
227
228 srate = params_rate(params);
229 spdif->reg_ch_sta_a &= ~TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
230 spdif->reg_ch_sta_b &= ~TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
231 switch (srate) {
232 case 32000:
233 spdifclock = 4096000;
234 spdif->reg_ch_sta_a |=
235 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
236 spdif->reg_ch_sta_b |=
237 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
238 break;
239 case 44100:
240 spdifclock = 5644800;
241 spdif->reg_ch_sta_a |=
242 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
243 spdif->reg_ch_sta_b |=
244 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
245 break;
246 case 48000:
247 spdifclock = 6144000;
248 spdif->reg_ch_sta_a |=
249 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
250 spdif->reg_ch_sta_b |=
251 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
252 break;
253 case 88200:
254 spdifclock = 11289600;
255 spdif->reg_ch_sta_a |=
256 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
257 spdif->reg_ch_sta_b |=
258 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
259 break;
260 case 96000:
261 spdifclock = 12288000;
262 spdif->reg_ch_sta_a |=
263 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
264 spdif->reg_ch_sta_b |=
265 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
266 break;
267 case 176400:
268 spdifclock = 22579200;
269 spdif->reg_ch_sta_a |=
270 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
271 spdif->reg_ch_sta_b |=
272 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
273 break;
274 case 192000:
275 spdifclock = 24576000;
276 spdif->reg_ch_sta_a |=
277 TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
278 spdif->reg_ch_sta_b |=
279 TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
280 break;
281 default:
282 return -EINVAL;
283 }
284
285 ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
286 if (ret) {
287 dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
288 return ret;
289 }
290
291 tegra30_spdif_enable_clocks(spdif);
292
293 tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_A,
294 spdif->reg_ch_sta_a);
295 tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_B,
296 spdif->reg_ch_sta_b);
297
298 tegra30_spdif_disable_clocks(spdif);
299
300 ret = tegra_hdmi_setup_audio_freq_source(srate, SPDIF);
301 if (ret) {
302 dev_err(dev, "Can't set HDMI audio freq source: %d\n", ret);
303 return ret;
304 }
305
306 return 0;
307}
308
309static void tegra30_spdif_start_playback(struct tegra30_spdif *spdif)
310{
311 tegra30_ahub_enable_tx_fifo(spdif->txcif);
312 spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_TX_EN_ENABLE |
313 TEGRA30_SPDIF_CTRL_TC_EN_ENABLE;
314 tegra30_spdif_write(spdif, TEGRA30_SPDIF_CTRL, spdif->reg_ctrl);
315}
316
317static void tegra30_spdif_stop_playback(struct tegra30_spdif *spdif)
318{
319 tegra30_ahub_disable_tx_fifo(spdif->txcif);
320 spdif->reg_ctrl &= ~(TEGRA30_SPDIF_CTRL_TX_EN_ENABLE |
321 TEGRA30_SPDIF_CTRL_TC_EN_ENABLE);
322 tegra30_spdif_write(spdif, TEGRA30_SPDIF_CTRL, spdif->reg_ctrl);
323}
324
325static int tegra30_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
326 struct snd_soc_dai *dai)
327{
328 struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
329
330 switch (cmd) {
331 case SNDRV_PCM_TRIGGER_START:
332 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
333 case SNDRV_PCM_TRIGGER_RESUME:
334 tegra30_spdif_enable_clocks(spdif);
335 tegra30_spdif_start_playback(spdif);
336 break;
337 case SNDRV_PCM_TRIGGER_STOP:
338 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
339 case SNDRV_PCM_TRIGGER_SUSPEND:
340 tegra30_spdif_stop_playback(spdif);
341 tegra30_spdif_disable_clocks(spdif);
342 break;
343 default:
344 return -EINVAL;
345 }
346
347 return 0;
348}
349
350static int tegra30_spdif_probe(struct snd_soc_dai *dai)
351{
352 struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
353
354 dai->playback_dma_data = &spdif->playback_dma_data;
355 dai->capture_dma_data = NULL;
356
357 return 0;
358}
359
360static struct snd_soc_dai_ops tegra30_spdif_dai_ops = {
361 .startup = tegra30_spdif_startup,
362 .shutdown = tegra30_spdif_shutdown,
363 .hw_params = tegra30_spdif_hw_params,
364 .trigger = tegra30_spdif_trigger,
365};
366
367struct snd_soc_dai_driver tegra30_spdif_dai = {
368 .name = DRV_NAME,
369 .probe = tegra30_spdif_probe,
370 .playback = {
371 .channels_min = 2,
372 .channels_max = 2,
373 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
374 SNDRV_PCM_RATE_48000,
375 .formats = SNDRV_PCM_FMTBIT_S16_LE,
376 },
377 .ops = &tegra30_spdif_dai_ops,
378};
379
380static __devinit int tegra30_spdif_platform_probe(struct platform_device *pdev)
381{
382 struct tegra30_spdif *spdif;
383 struct resource *mem, *memregion;
384 int ret;
385 u32 reg_val;
386
387 spdif = kzalloc(sizeof(struct tegra30_spdif), GFP_KERNEL);
388 if (!spdif) {
389 dev_err(&pdev->dev, "Can't allocate tegra30_spdif\n");
390 ret = -ENOMEM;
391 goto exit;
392 }
393 dev_set_drvdata(&pdev->dev, spdif);
394
395 spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
396 if (IS_ERR(spdif->clk_spdif_out)) {
397 dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
398 ret = PTR_ERR(spdif->clk_spdif_out);
399 goto err_free;
400 }
401
402 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
403 if (!mem) {
404 dev_err(&pdev->dev, "No memory resource\n");
405 ret = -ENODEV;
406 goto err_clk_put_spdif;
407 }
408
409 memregion = request_mem_region(mem->start, resource_size(mem),
410 DRV_NAME);
411 if (!memregion) {
412 dev_err(&pdev->dev, "Memory region already claimed\n");
413 ret = -EBUSY;
414 goto err_clk_put_spdif;
415 }
416
417 spdif->regs = ioremap(mem->start, resource_size(mem));
418 if (!spdif->regs) {
419 dev_err(&pdev->dev, "ioremap failed\n");
420 ret = -ENOMEM;
421 goto err_release;
422 }
423
424 tegra30_spdif_enable_clocks(spdif);
425
426 reg_val = TEGRA30_SPDIF_CIF_TXD_CTRL_DIRECTION_RXCIF |
427 TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT16 |
428 TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT16 |
429 TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH2 |
430 TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH2 |
431 (3 << TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_SHIFT);
432
433 tegra30_spdif_write(spdif, TEGRA30_SPDIF_CIF_TXD_CTRL, reg_val);
434
435 tegra30_spdif_disable_clocks(spdif);
436
437 ret = snd_soc_register_dai(&pdev->dev, &tegra30_spdif_dai);
438 if (ret) {
439 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
440 ret = -ENOMEM;
441 goto err_unmap;
442 }
443
444 tegra30_spdif_debug_add(spdif);
445
446 return 0;
447
448err_unmap:
449 iounmap(spdif->regs);
450err_release:
451 release_mem_region(mem->start, resource_size(mem));
452err_clk_put_spdif:
453 clk_put(spdif->clk_spdif_out);
454err_free:
455 kfree(spdif);
456exit:
457 return ret;
458}
459
460static int __devexit tegra30_spdif_platform_remove(struct platform_device *pdev)
461{
462 struct tegra30_spdif *spdif = dev_get_drvdata(&pdev->dev);
463 struct resource *res;
464
465 snd_soc_unregister_dai(&pdev->dev);
466
467 tegra30_spdif_debug_remove(spdif);
468
469 iounmap(spdif->regs);
470
471 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
472 release_mem_region(res->start, resource_size(res));
473
474 clk_put(spdif->clk_spdif_out);
475
476 kfree(spdif);
477
478 return 0;
479}
480
481static struct platform_driver tegra30_spdif_driver = {
482 .driver = {
483 .name = DRV_NAME,
484 .owner = THIS_MODULE,
485 },
486 .probe = tegra30_spdif_platform_probe,
487 .remove = __devexit_p(tegra30_spdif_platform_remove),
488};
489
490static int __init snd_tegra30_spdif_init(void)
491{
492 return platform_driver_register(&tegra30_spdif_driver);
493}
494module_init(snd_tegra30_spdif_init);
495
496static void __exit snd_tegra30_spdif_exit(void)
497{
498 platform_driver_unregister(&tegra30_spdif_driver);
499}
500module_exit(snd_tegra30_spdif_exit);
501
502MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
503MODULE_DESCRIPTION("Tegra30 SPDIF ASoC driver");
504MODULE_LICENSE("GPL");
505MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra30_spdif.h b/sound/soc/tegra/tegra30_spdif.h
new file mode 100644
index 00000000000..c4763c31b25
--- /dev/null
+++ b/sound/soc/tegra/tegra30_spdif.h
@@ -0,0 +1,777 @@
1/*
2 * tegra30_spdif.h - Definitions for Tegra30 SPDIF driver
3 *
4 * Author: Sumit Bhattacharya <sumitb@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2011, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#ifndef __TEGRA30_SPDIF_H__
32#define __TEGRA30_SPDIF_H__
33
34#include "tegra_pcm.h"
35#include "tegra30_ahub.h"
36
37/* Register offsets from TEGRA_SPDIF_BASE */
38
39#define TEGRA30_SPDIF_CTRL 0x0
40#define TEGRA30_SPDIF_STROBE_CTRL 0x4
41#define TEGRA30_SPDIF_CIF_TXD_CTRL 0x08
42#define TEGRA30_SPDIF_CIF_RXD_CTRL 0x0C
43#define TEGRA30_SPDIF_CIF_TXU_CTRL 0x10
44#define TEGRA30_SPDIF_CIF_RXU_CTRL 0x14
45#define TEGRA30_SPDIF_CH_STA_RX_A 0x18
46#define TEGRA30_SPDIF_CH_STA_RX_B 0x1C
47#define TEGRA30_SPDIF_CH_STA_RX_C 0x20
48#define TEGRA30_SPDIF_CH_STA_RX_D 0x24
49#define TEGRA30_SPDIF_CH_STA_RX_E 0x28
50#define TEGRA30_SPDIF_CH_STA_RX_F 0x2C
51#define TEGRA30_SPDIF_CH_STA_TX_A 0x30
52#define TEGRA30_SPDIF_CH_STA_TX_B 0x34
53#define TEGRA30_SPDIF_CH_STA_TX_C 0x38
54#define TEGRA30_SPDIF_CH_STA_TX_D 0x3C
55#define TEGRA30_SPDIF_CH_STA_TX_E 0x40
56#define TEGRA30_SPDIF_CH_STA_TX_F 0x44
57#define TEGRA30_SPDIF_FLOWCTL_CTRL 0x70
58#define TEGRA30_SPDIF_TX_STEP 0x74
59#define TEGRA30_SPDIF_FLOW_STATUS 0x78
60#define TEGRA30_SPDIF_FLOW_TOTAL 0x7c
61#define TEGRA30_SPDIF_FLOW_OVER 0x80
62#define TEGRA30_SPDIF_FLOW_UNDER 0x84
63#define TEGRA30_SPDIF_LCOEF_1_4_0 0x88
64#define TEGRA30_SPDIF_LCOEF_1_4_1 0x8c
65#define TEGRA30_SPDIF_LCOEF_1_4_2 0x90
66#define TEGRA30_SPDIF_LCOEF_1_4_3 0x94
67#define TEGRA30_SPDIF_LCOEF_1_4_4 0x98
68#define TEGRA30_SPDIF_LCOEF_1_4_5 0x9c
69#define TEGRA30_SPDIF_LCOEF_2_4_0 0xa0
70#define TEGRA30_SPDIF_LCOEF_2_4_1 0xa4
71#define TEGRA30_SPDIF_LCOEF_2_4_2 0xa8
72
73/* Fields in TEGRA30_SPDIF_CTRL */
74#define TEGRA30_SPDIF_CTRL_FLOWCTL_EN_ENABLE (1<<31)
75#define TEGRA30_SPDIF_CTRL_CAP_LC_LEFT_CH (1<<30)
76#define TEGRA30_SPDIF_CTRL_RX_EN_ENABLE (1<<29)
77#define TEGRA30_SPDIF_CTRL_TX_EN_ENABLE (1<<28)
78#define TEGRA30_SPDIF_CTRL_TC_EN_ENABLE (1<<27)
79#define TEGRA30_SPDIF_CTRL_TU_EN_ENABLE (1<<26)
80#define TEGRA30_SPDIF_CTRL_IE_P_RSVD_ENABLE (1<<23)
81#define TEGRA30_SPDIF_CTRL_IE_B_RSVD_ENABLE (1<<22)
82#define TEGRA30_SPDIF_CTRL_IE_C_RSVD_ENABLE (1<<21)
83#define TEGRA30_SPDIF_CTRL_IE_U_RSVD_ENABLE (1<<20)
84#define TEGRA30_SPDIF_CTRL_LBK_EN_ENABLE (1<<15)
85#define TEGRA30_SPDIF_CTRL_PACK_ENABLE (1<<14)
86
87#define TEGRA30_SPDIF_BIT_MODE16 0
88#define TEGRA30_SPDIF_BIT_MODE20 1
89#define TEGRA30_SPDIF_BIT_MODE24 2
90#define TEGRA30_SPDIF_BIT_MODERAW 3
91
92#define TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT 12
93#define TEGRA30_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT)
94#define TEGRA30_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA30_SPDIF_BIT_MODE16 << TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT)
95#define TEGRA30_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA30_SPDIF_BIT_MODE20 << TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT)
96#define TEGRA30_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA30_SPDIF_BIT_MODE24 << TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT)
97#define TEGRA30_SPDIF_CTRL_BIT_MODE_RAW (TEGRA30_SPDIF_BIT_MODERAW << TEGRA30_SPDIF_CTRL_BIT_MODE_SHIFT)
98
99#define TEGRA30_SPDIF_CTRL_CG_EN_ENABLE (1<<11)
100
101#define TEGRA30_SPDIF_CTRL_OBS_SEL_SHIFT 8
102#define TEGRA30_SPDIF_CTRL_OBS_SEL_NASK (0x7 << TEGRA30_SPDIF_CTRL_OBS_SEL_SHIFT)
103
104#define TEGRA30_SPDIF_CTRL_SOFT_RESET_ENABLE (1<<7)
105
106/* Fields in TEGRA30_SPDIF_STROBE_CTRL */
107#define TEGRA30_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16
108#define TEGRA30_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA30_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
109
110#define TEGRA30_SPDIF_STROBE_CTRL_STROBE (1<<15)
111
112#define TEGRA30_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8
113#define TEGRA30_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA30_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
114
115#define TEGRA30_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0
116#define TEGRA30_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA30_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
117
118/* Fields in TEGRA30_SPDIF_CIF_TXD_CTRL */
119#define TEGRA30_SPDIF_CIF_TXD_CTRL_MONO_CONV_COPY (1<<0)
120#define TEGRA30_SPDIF_CIF_TXD_CTRL_TRUNCATE_CHOP (1<<1)
121#define TEGRA30_SPDIF_CIF_TXD_CTRL_DIRECTION_RXCIF (1<<2)
122#define TEGRA30_SPDIF_CIF_TXD_CTRL_REPLICATE_ENABLE (1<<3)
123
124#define TEGRA30_SPDIF_CIF_STEREO_CH0 0
125#define TEGRA30_SPDIF_CIF_STEREO_CH1 1
126#define TEGRA30_SPDIF_CIF_STEREO_AVG 2
127#define TEGRA30_SPDIF_CIF_STEREO_RSVD 3
128
129#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT 4
130#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_MASK \
131 (0x3 << TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT)
132#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_CH0 \
133 (TEGRA30_SPDIF_CIF_STEREO_CH0 << TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT)
134#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_CH1 \
135 (TEGRA30_SPDIF_CIF_STEREO_CH1 << TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT)
136#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_AVG \
137 (TEGRA30_SPDIF_CIF_STEREO_AVG << TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT)
138#define TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_RSVD \
139 (TEGRA30_SPDIF_CIF_STEREO_RSVD << TEGRA30_SPDIF_CIF_TXD_CTRL_STEREO_CONV_SHIFT)
140
141#define TEGRA30_SPDIF_CIF_EXPAND_ZERO 0
142#define TEGRA30_SPDIF_CIF_EXPAND_ONE 1
143#define TEGRA30_SPDIF_CIF_EXPAND_LFSR 2
144#define TEGRA30_SPDIF_CIF_EXPAND_RSVD 3
145
146#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT 6
147#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_MASK \
148 (0x3 << TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT)
149#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_ZERO \
150 (TEGRA30_SPDIF_CIF_EXPAND_ZERO << TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT)
151#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_ONE \
152 (TEGRA30_SPDIF_CIF_EXPAND_ONE << TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT)
153#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_LFSR \
154 (TEGRA30_SPDIF_CIF_EXPAND_LFSR << TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT)
155#define TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_RSVD \
156 (TEGRA30_SPDIF_CIF_EXPAND_RSVD << TEGRA30_SPDIF_CIF_TXD_CTRL_EXPAND_SHIFT)
157
158#define TEGRA30_SPDIF_CIF_BIT4 0
159#define TEGRA30_SPDIF_CIF_BIT8 1
160#define TEGRA30_SPDIF_CIF_BIT12 2
161#define TEGRA30_SPDIF_CIF_BIT16 3
162#define TEGRA30_SPDIF_CIF_BIT20 4
163#define TEGRA30_SPDIF_CIF_BIT24 5
164#define TEGRA30_SPDIF_CIF_BIT28 6
165#define TEGRA30_SPDIF_CIF_BIT32 7
166
167#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT 8
168#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_MASK \
169 (0x7 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
170#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT4 \
171 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
172#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT8 \
173 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
174#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT12 \
175 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
176#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT16 \
177 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
178#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT20 \
179 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
180#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT24 \
181 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
182#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT28 \
183 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
184#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT32 \
185 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BITS_SHIFT)
186
187
188#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT 12
189#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_MASK \
190 (0x7 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
191#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT4 \
192 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
193#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT8 \
194 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
195#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT12 \
196 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
197#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT16 \
198 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
199#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT20 \
200 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
201#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT24 \
202 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
203#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT28 \
204 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
205#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT32 \
206 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BITS_SHIFT)
207
208#define TEGRA30_SPDIF_CIF_CH1 0
209#define TEGRA30_SPDIF_CIF_CH2 1
210#define TEGRA30_SPDIF_CIF_CH3 2
211#define TEGRA30_SPDIF_CIF_CH4 3
212#define TEGRA30_SPDIF_CIF_CH5 4
213#define TEGRA30_SPDIF_CIF_CH6 5
214#define TEGRA30_SPDIF_CIF_CH7 6
215#define TEGRA30_SPDIF_CIF_CH8 7
216
217#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT 16
218#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_MASK \
219 (0x7 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
220#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH1 \
221 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
222#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH2 \
223 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
224#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH3 \
225 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
226#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH4 \
227 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
228#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH5 \
229 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
230#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH6 \
231 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
232#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH7 \
233 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
234#define TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH8 \
235 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH_SHIFT)
236
237
238#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT 24
239#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_MASK \
240 (0x7 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
241#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH1 \
242 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
243#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH2 \
244 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
245#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH3 \
246 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
247#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH4 \
248 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
249#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH5 \
250 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
251#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH6 \
252 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
253#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH7 \
254 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
255#define TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH8 \
256 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH_SHIFT)
257
258#define TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_SHIFT 28
259#define TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_MASK (0x7 << TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_SHIFT)
260
261/* Fields in TEGRA30_TEGRA30_SPDIF_CIF_RXD_CTRL */
262#define TEGRA30_SPDIF_CIF_RXD_CTRL_MONO_CONV_COPY (1<<0)
263#define TEGRA30_SPDIF_CIF_RXD_CTRL_TRUNCATE_CHOP (1<<1)
264#define TEGRA30_SPDIF_CIF_RXD_CTRL_DIRECTION_RXCIF (1<<2)
265#define TEGRA30_SPDIF_CIF_RXD_CTRL_REPLICATE_ENABLE (1<<3)
266
267#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT 4
268#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_MASK \
269 (0x3 << TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT)
270#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_CH0 \
271 (TEGRA30_SPDIF_CIF_STEREO_CH0 << TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT)
272#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_CH1 \
273 (TEGRA30_SPDIF_CIF_STEREO_CH1 << TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT)
274#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_AVG \
275 (TEGRA30_SPDIF_CIF_STEREO_AVG << TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT)
276#define TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_RSVD \
277 (TEGRA30_SPDIF_CIF_STEREO_RSVD << TEGRA30_SPDIF_CIF_RXD_CTRL_STEREO_CONV_SHIFT)
278
279
280#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_SHIFT 6
281#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_MASK \
282 (0x3 << TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_SHIFT)
283#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_ZERO \
284 (TEGRA30_SPDIF_CIF_EXPAND_ZERO << TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_SHIFT)
285#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_ONE \
286 (TEGRA30_SPDIF_CIF_EXPAND_ONE << TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_SHIFT)
287#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_LFSR \
288 (TEGRA30_SPDIF_CIF_EXPAND_LFSR << TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_SHIFT)
289#define TEGRA30_SPDIF_CIF_RXD_CTRL_EXPAND_RSVD \
290
291
292#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT 8
293#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_MASK \
294 (0x7 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
295#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT4 \
296 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
297#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT8 \
298 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
299#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT12 \
300 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
301#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT16 \
302 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
303#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT20 \
304 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
305#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT24 \
306 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
307#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT28 \
308 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
309#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BIT32 \
310 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_BITS_SHIFT)
311
312#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT 12
313#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_MASK \
314 (0x7 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
315#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT4 \
316 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
317#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT8 \
318 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
319#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT12 \
320 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
321#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT16 \
322 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
323#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT20 \
324 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
325#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT24 \
326 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
327#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT28 \
328 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
329#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BIT32 \
330 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_BITS_SHIFT)
331
332
333#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT 16
334#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_MASK \
335 (0x7 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
336#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH1 \
337 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
338#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH2 \
339 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
340#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH3 \
341 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
342#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH4 \
343 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
344#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH5 \
345 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
346#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH6 \
347 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
348#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH7 \
349 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
350#define TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH8 \
351 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_RXD_CTRL_CLIENT_CH_SHIFT)
352
353
354#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT 24
355#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_MASK \
356 (0x7 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
357#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH1 \
358 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
359#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH2 \
360 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
361#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH3 \
362 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
363#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH4 \
364 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
365#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH5 \
366 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
367#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH6 \
368 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
369#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH7 \
370 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
371#define TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CH8 \
372 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_RXD_CTRL_AUDIO_CHANNELS_SHIFT)
373
374#define TEGRA30_SPDIF_CIF_RXD_CTRL_FIFO_TH_SHIFT 28
375#define TEGRA30_SPDIF_CIF_RXD_CTRL_FIFO_TH_MASK (0x7 << TEGRA30_SPDIF_CIF_RXD_CTRL_FIFO_TH_SHIFT)
376
377/* Fields in TEGRA30_TEGRA30_SPDIF_CIF_TXU_CTRL */
378#define TEGRA30_SPDIF_CIF_TXU_CTRL_MONO_CONV_COPY (1<<0)
379#define TEGRA30_SPDIF_CIF_TXU_CTRL_TRUNCATE_CHOP (1<<1)
380#define TEGRA30_SPDIF_CIF_TXU_CTRL_DIRECTION_RXCIF (1<<2)
381#define TEGRA30_SPDIF_CIF_TXU_CTRL_REPLICATE_ENABLE (1<<3)
382
383
384#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_SHIFT 4
385#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_MASK \
386 (0x3 << TEGRA30_SPDIF_CIF_TXU_CTRL_0_STEREO_CONV_SHIFT)
387#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_CH0 \
388 (TEGRA30_SPDIF_CIF_STEREO_CH0 << TEGRA30_SPDIF_CIF_TXU_CTRL_0_STEREO_CONV_SHIFT)
389#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_CH1 \
390 (TEGRA30_SPDIF_CIF_STEREO_CH1 << TEGRA30_SPDIF_CIF_TXU_CTRL_0_STEREO_CONV_SHIFT)
391#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_AVG \
392 (TEGRA30_SPDIF_CIF_STEREO_AVG << TEGRA30_SPDIF_CIF_TXU_CTRL_0_STEREO_CONV_SHIFT)
393#define TEGRA30_SPDIF_CIF_TXU_CTRL_STEREO_CONV_RSVD \
394 (TEGRA30_SPDIF_CIF_STEREO_RSVD << TEGRA30_SPDIF_CIF_TXU_CTRL_0_STEREO_CONV_SHIFT)
395
396
397#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT 6
398#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_MASK \
399 (0x3 << TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT)
400#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_ZERO \
401 (TEGRA30_SPDIF_CIF_EXPAND_ZERO << TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT)
402#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_ONE \
403 (TEGRA30_SPDIF_CIF_EXPAND_ONE << TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT)
404#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_LFSR \
405 (TEGRA30_SPDIF_CIF_EXPAND_LFSR << TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT)
406#define TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_RSVD \
407 (TEGRA30_SPDIF_CIF_EXPAND_RSVD << TEGRA30_SPDIF_CIF_TXU_CTRL_EXPAND_SHIFT)
408
409
410#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT 8
411#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_MASK \
412 (0x7 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
413#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT4 \
414 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
415#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT8 \
416 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
417#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT12 \
418 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
419#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT16 \
420 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
421#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT20 \
422 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
423#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT24 \
424 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
425#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT28 \
426 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
427#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BIT32 \
428 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_BITS_SHIFT)
429
430
431#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT 12
432#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_MASK \
433 (0x7 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
434#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT4 \
435 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
436#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT8 \
437 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
438#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT12 \
439 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
440#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT16 \
441 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
442#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT20 \
443 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
444#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT24 \
445 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
446#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT28 \
447 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
448#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BIT32 \
449 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_BITS_SHIFT)
450
451
452#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT 16
453#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_MASK \
454 (0x7 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
455#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH1 \
456 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
457#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH2 \
458 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
459#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH3 \
460 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
461#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH4 \
462 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
463#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH5 \
464 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
465#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH6 \
466 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
467#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH7 \
468 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
469#define TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH8 \
470 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_TXU_CTRL_CLIENT_CH_SHIFT)
471
472
473#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT 24
474#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_MASK \
475 (0x7 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
476#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH1 \
477 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
478#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH2 \
479 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
480#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH3 \
481 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
482#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH4 \
483 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
484#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH5 \
485 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
486#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH6 \
487 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
488#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH7 \
489 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
490#define TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH8 \
491 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_TXU_CTRL_AUDIO_CH_SHIFT)
492
493#define TEGRA30_SPDIF_CIF_TXU_CTRL_FIFO_TH_SHIFT 28
494#define TEGRA30_SPDIF_CIF_TXU_CTRL_FIFO_TH_MASK (0x7 << TEGRA30_SPDIF_CIF_TXU_CTRL_FIFO_TH_SHIFT)
495
496/* Fields in TEGRA30_TEGRA30_SPDIF_CIF_RXU_CTRL */
497#define TEGRA30_SPDIF_CIF_RXU_CTRL_MONO_CONV_COPY (1<<0)
498#define TEGRA30_SPDIF_CIF_RXU_CTRL_TRUNCATE_CHOP (1<<1)
499#define TEGRA30_SPDIF_CIF_RXU_CTRL_DIRECTION_RXCIF (1<<2)
500#define TEGRA30_SPDIF_CIF_RXU_CTRL_REPLICATE_ENABLE (1<<3)
501
502
503#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_SHIFT 4
504#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_MASK \
505 (0x3 << TEGRA30_SPDIF_CIF_RXU_CTRL_0_STEREO_CONV_SHIFT)
506#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_CH0 \
507 (TEGRA30_SPDIF_CIF_STEREO_CH0 << TEGRA30_SPDIF_CIF_RXU_CTRL_0_STEREO_CONV_SHIFT)
508#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_CH1 \
509 (TEGRA30_SPDIF_CIF_STEREO_CH1 << TEGRA30_SPDIF_CIF_RXU_CTRL_0_STEREO_CONV_SHIFT)
510#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_AVG \
511 (TEGRA30_SPDIF_CIF_STEREO_AVG << TEGRA30_SPDIF_CIF_RXU_CTRL_0_STEREO_CONV_SHIFT)
512#define TEGRA30_SPDIF_CIF_RXU_CTRL_STEREO_CONV_RSVD \
513 (TEGRA30_SPDIF_CIF_STEREO_RSVD << TEGRA30_SPDIF_CIF_RXU_CTRL_0_STEREO_CONV_SHIFT)
514
515
516#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT 6
517#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_MASK \
518 (0x3 << TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT)
519#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_ZERO \
520 (TEGRA30_SPDIF_CIF_EXPAND_ZERO << TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT)
521#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_ONE \
522 (TEGRA30_SPDIF_CIF_EXPAND_ONE << TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT)
523#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_LFSR \
524 (TEGRA30_SPDIF_CIF_EXPAND_LFSR << TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT)
525#define TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_RSVD \
526 (TEGRA30_SPDIF_CIF_EXPAND_RSVD << TEGRA30_SPDIF_CIF_RXU_CTRL_EXPAND_SHIFT)
527
528
529#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT 8
530#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_MASK \
531 (0x7 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
532#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT4 \
533 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
534#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT8 \
535 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
536#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT12 \
537 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
538#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT16 \
539 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
540#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT20 \
541 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
542#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT24 \
543 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
544#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT28 \
545 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
546#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BIT32 \
547 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_BITS_SHIFT)
548
549
550#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT 12
551#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_MASK \
552 (0x7 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
553#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT4 \
554 (TEGRA30_SPDIF_CIF_BIT4 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
555#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT8 \
556 (TEGRA30_SPDIF_CIF_BIT8 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
557#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT12 \
558 (TEGRA30_SPDIF_CIF_BIT12 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
559#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT16 \
560 (TEGRA30_SPDIF_CIF_BIT16 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
561#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT20 \
562 (TEGRA30_SPDIF_CIF_BIT20 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
563#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT24 \
564 (TEGRA30_SPDIF_CIF_BIT24 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
565#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT28 \
566 (TEGRA30_SPDIF_CIF_BIT28 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
567#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BIT32 \
568 (TEGRA30_SPDIF_CIF_BIT32 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_BITS_SHIFT)
569
570
571#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT 16
572#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_MASK \
573 (0x7 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
574#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH1 \
575 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
576#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH2 \
577 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
578#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH3 \
579 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
580#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH4 \
581 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
582#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH5 \
583 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
584#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH6 \
585 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
586#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH7 \
587 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
588#define TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH8 \
589 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_RXU_CTRL_CLIENT_CH_SHIFT)
590
591
592#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT 24
593#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_MASK \
594 (0x7 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
595#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH1 \
596 (TEGRA30_SPDIF_CIF_CH1 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
597#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH2 \
598 (TEGRA30_SPDIF_CIF_CH2 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
599#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH3 \
600 (TEGRA30_SPDIF_CIF_CH3 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
601#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH4 \
602 (TEGRA30_SPDIF_CIF_CH4 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
603#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH5 \
604 (TEGRA30_SPDIF_CIF_CH5 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
605#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH6 \
606 (TEGRA30_SPDIF_CIF_CH6 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
607#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH7 \
608 (TEGRA30_SPDIF_CIF_CH7 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
609#define TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH8 \
610 (TEGRA30_SPDIF_CIF_CH8 << TEGRA30_SPDIF_CIF_RXU_CTRL_AUDIO_CH_SHIFT)
611
612#define TEGRA30_SPDIF_CIF_RXU_CTRL_FIFO_TH_SHIFT 28
613#define TEGRA30_SPDIF_CIF_RXU_CTRL_FIFO_TH_MASK (0x7 << TEGRA30_SPDIF_CIF_RXU_CTRL_FIFO_TH_SHIFT)
614
615/* Fields in TEGRA30_SPDIF_CH_STA_RX_A */
616/* Fields in TEGRA30_SPDIF_CH_STA_RX_B */
617/* Fields in TEGRA30_SPDIF_CH_STA_RX_C */
618/* Fields in TEGRA30_SPDIF_CH_STA_RX_D */
619/* Fields in TEGRA30_SPDIF_CH_STA_RX_E */
620/* Fields in TEGRA30_SPDIF_CH_STA_RX_F */
621
622/*
623 * The 6-word receive channel data page buffer holds a block (192 frames) of
624 * channel status information. The order of receive is from LSB to MSB
625 * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
626 */
627
628/* Fields in TEGRA30_SPDIF_CH_STA_TX_A */
629#define TEGRA30_SPDIF_CH_STA_TX_A_SF_22050 0x4
630#define TEGRA30_SPDIF_CH_STA_TX_A_SF_24000 0x6
631#define TEGRA30_SPDIF_CH_STA_TX_A_SF_32000 0x3
632#define TEGRA30_SPDIF_CH_STA_TX_A_SF_44100 0x0
633#define TEGRA30_SPDIF_CH_STA_TX_A_SF_48000 0x2
634#define TEGRA30_SPDIF_CH_STA_TX_A_SF_88200 0x8
635#define TEGRA30_SPDIF_CH_STA_TX_A_SF_96000 0xA
636#define TEGRA30_SPDIF_CH_STA_TX_A_SF_176400 0xC
637#define TEGRA30_SPDIF_CH_STA_TX_A_SF_192000 0xE
638
639#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT 24
640#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK \
641 (0xF << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
642#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_22050 \
643 (TEGRA30_SPDIF_CH_STA_TX_A_SF_22050 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
644#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_24000 \
645 (TEGRA30_SPDIF_CH_STA_TX_A_SF_24000 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
646#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000 \
647 (TEGRA30_SPDIF_CH_STA_TX_A_SF_32000 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
648#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100 \
649 (TEGRA30_SPDIF_CH_STA_TX_A_SF_44100 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
650#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000 \
651 (TEGRA30_SPDIF_CH_STA_TX_A_SF_48000 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
652#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200 \
653 (TEGRA30_SPDIF_CH_STA_TX_A_SF_88200 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
654#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000 \
655 (TEGRA30_SPDIF_CH_STA_TX_A_SF_96000 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
656#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400 \
657 (TEGRA30_SPDIF_CH_STA_TX_A_SF_176400 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
658#define TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000 \
659 (TEGRA30_SPDIF_CH_STA_TX_A_SF_192000 << TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
660
661/* Fields in TEGRA30_SPDIF_CH_STA_TX_B */
662#define TEGRA30_SPDIF_CH_STA_TX_B_SF_8000 0x6
663#define TEGRA30_SPDIF_CH_STA_TX_B_SF_11025 0xA
664#define TEGRA30_SPDIF_CH_STA_TX_B_SF_12000 0x2
665#define TEGRA30_SPDIF_CH_STA_TX_B_SF_16000 0x8
666#define TEGRA30_SPDIF_CH_STA_TX_B_SF_22050 0xB
667#define TEGRA30_SPDIF_CH_STA_TX_B_SF_24000 0x9
668#define TEGRA30_SPDIF_CH_STA_TX_B_SF_32000 0xC
669#define TEGRA30_SPDIF_CH_STA_TX_B_SF_44100 0xF
670#define TEGRA30_SPDIF_CH_STA_TX_B_SF_48000 0xD
671#define TEGRA30_SPDIF_CH_STA_TX_B_SF_88200 0x7
672#define TEGRA30_SPDIF_CH_STA_TX_B_SF_96000 0x5
673#define TEGRA30_SPDIF_CH_STA_TX_B_SF_176400 0x3
674#define TEGRA30_SPDIF_CH_STA_TX_B_SF_192000 0x1
675
676#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT 4
677#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK \
678 (0xF << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
679#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_8000 \
680 (TEGRA30_SPDIF_CH_STA_TX_B_SF_8000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
681#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_11025 \
682 (TEGRA30_SPDIF_CH_STA_TX_B_SF_11025 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
683#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_12000 \
684 (TEGRA30_SPDIF_CH_STA_TX_B_SF_12000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
685#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_16000 \
686 (TEGRA30_SPDIF_CH_STA_TX_B_SF_16000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
687#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_22050 \
688 (TEGRA30_SPDIF_CH_STA_TX_B_SF_22025 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
689#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_24000 \
690 (TEGRA30_SPDIF_CH_STA_TX_B_SF_24000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
691#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000 \
692 (TEGRA30_SPDIF_CH_STA_TX_B_SF_32000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
693#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100 \
694 (TEGRA30_SPDIF_CH_STA_TX_B_SF_44100 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
695#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000 \
696 (TEGRA30_SPDIF_CH_STA_TX_B_SF_48000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
697#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200 \
698 (TEGRA30_SPDIF_CH_STA_TX_B_SF_88200 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
699#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000 \
700 (TEGRA30_SPDIF_CH_STA_TX_B_SF_96000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
701#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400 \
702 (TEGRA30_SPDIF_CH_STA_TX_B_SF_176400 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
703#define TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000 \
704 (TEGRA30_SPDIF_CH_STA_TX_B_SF_192000 << TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
705
706/* Fields in TEGRA30_SPDIF_CH_STA_TX_C */
707/* Fields in TEGRA30_SPDIF_CH_STA_TX_D */
708/* Fields in TEGRA30_SPDIF_CH_STA_TX_E */
709/* Fields in TEGRA30_SPDIF_CH_STA_TX_F */
710
711/* Fields in TEGRA30_SPDIF_FLOWCTL_CTRL */
712#define TEGRA30_SPDIF_FLOWCTL_CTRL_FILTER_QUAD (1<<31)
713
714/* Fields in TEGRA30_SPDIF_TX_STEP */
715#define TEGRA30_SPDIF_TX_STEP_STEP_SIZE_SHIFT 0
716#define TEGRA30_SPDIF_TX_STEP_STEP_SIZE_MASK (0xffff << TEGRA30_SPDIF_TX_STEP_STEP_SIZE_SHIFT)
717
718/* Fields in TEGRA30_SPDIF_FLOW_STATUS */
719#define TEGRA30_SPDIF_FLOW_STATUS_COUNTER_EN_ENABLE (1<<1)
720#define TEGRA30_SPDIF_FLOW_STATUS_MONITOR_CLR_CLEAR (1<<2)
721#define TEGRA30_SPDIF_FLOW_STATUS_COUNTER_CLR_CLEAR (1<<3)
722#define TEGRA30_SPDIF_FLOW_STATUS_MONITOR_INT_EN_ENABLE (1<<4)
723#define TEGRA30_SPDIF_FLOW_STATUS_FLOW_OVERFLOW_OVER (1<<30)
724#define TEGRA30_SPDIF_FLOW_STATUS_FLOW_UNDERFLOW_UNDER (1<<31)
725
726/* Fields in TEGRA30_SPDIF_FLOW_TOTAL */
727/* Fields in TEGRA30_SPDIF_FLOW_OVER */
728/* Fields in TEGRA30_SPDIF_FLOW_UNDER */
729
730/* Fields in TEGRA30_SPDIF_LCOEF_1_4_0 */
731#define TEGRA30_SPDIF_LCOEF_1_4_0_COEF_SHIFT 0
732#define TEGRA30_SPDIF_LCOEF_1_4_0_COEF_MASK (0xffff << TEGRA30_TEGRA30_SPDIF_LCOEF_1_4_0_COEF_SHIFT)
733
734/* Fields in TEGRA30_SPDIF_LCOEF_1_4_1 */
735#define TEGRA30_SPDIF_LCOEF_1_4_1_COEF_SHIFT 0
736#define TEGRA30_SPDIF_LCOEF_1_4_1_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_1_4_1_COEF_SHIFT)
737
738/* Fields in TEGRA30_SPDIF_LCOEF_1_4_2 */
739#define TEGRA30_SPDIF_LCOEF_1_4_2_COEF_SHIFT 0
740#define TEGRA30_SPDIF_LCOEF_1_4_2_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_1_4_2_COEF_SHIFT)
741
742/* Fields in TEGRA30_SPDIF_LCOEF_1_4_3 */
743#define TEGRA30_SPDIF_LCOEF_1_4_3_COEF_SHIFT 0
744#define TEGRA30_SPDIF_LCOEF_1_4_3_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_1_4_3_COEF_SHIFT)
745
746/* Fields in TEGRA30_SPDIF_LCOEF_1_4_4 */
747#define TEGRA30_SPDIF_LCOEF_1_4_4_COEF_SHIFT 0
748#define TEGRA30_SPDIF_LCOEF_1_4_4_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_1_4_4_COEF_SHIFT)
749
750/* Fields in TEGRA30_SPDIF_LCOEF_1_4_5 */
751#define TEGRA30_SPDIF_LCOEF_1_4_5_COEF_SHIFT 0
752#define TEGRA30_SPDIF_LCOEF_1_4_5_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_1_4_5_COEF_SHIFT)
753
754/* Fields in TEGRA30_SPDIF_LCOEF_2_4_0 */
755#define TEGRA30_SPDIF_LCOEF_2_4_0_COEF_SHIFT 0
756#define TEGRA30_SPDIF_LCOEF_2_4_0_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_2_4_0_COEF_SHIFT)
757
758/* Fields in TEGRA30_SPDIF_LCOEF_2_4_1 */
759#define TEGRA30_SPDIF_LCOEF_2_4_1_COEF_SHIFT 0
760#define TEGRA30_SPDIF_LCOEF_2_4_1_COEF_MASK (0xffff << TEGRA30_SPDIF_LCOEF_2_4_1_COEF_SHIFT)
761
762/* Fields in TEGRA30_SPDIF_LCOEF_2_4_2 */
763#define TEGRA30_SPDIF_LCOEF_2_4_2_COEF_SHIFT 0
764#define TEGRA30_SPDIF_LCOEF_2_4_2_COEF_MASK (0xffff << SPDIF_LCOEF_2_4_2_COEF_SHIFT)
765
766struct tegra30_spdif {
767 struct clk *clk_spdif_out;
768 enum tegra30_ahub_txcif txcif;
769 struct tegra_pcm_dma_params playback_dma_data;
770 void __iomem *regs;
771 struct dentry *debug;
772 u32 reg_ctrl;
773 u32 reg_ch_sta_a;
774 u32 reg_ch_sta_b;
775};
776
777#endif
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
new file mode 100644
index 00000000000..6d38934138b
--- /dev/null
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -0,0 +1,1281 @@
1/*
2 * tegra_aic326x.c - Tegra machine ASoC driver for boards using TI 3262 codec.
3 *
4 * Author: Vinod G. <vinodg@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2010, 2011 Nvidia Graphics Pvt. Ltd.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 *
25 */
26
27#include <asm/mach-types.h>
28
29#include <linux/module.h>
30#include <linux/platform_device.h>
31#include <linux/slab.h>
32#include <linux/gpio.h>
33#include <linux/regulator/consumer.h>
34#ifdef CONFIG_SWITCH
35#include <linux/switch.h>
36#endif
37
38#include <mach/tegra_aic326x_pdata.h>
39
40#include <sound/core.h>
41#include <sound/jack.h>
42#include <sound/pcm.h>
43#include <sound/pcm_params.h>
44#include <sound/soc.h>
45
46#include "../codecs/tlv320aic326x.h"
47
48#include "tegra_pcm.h"
49#include "tegra_asoc_utils.h"
50
51#ifdef CONFIG_ARCH_TEGRA_2x_SOC
52#include "tegra20_das.h"
53#else
54#include "tegra30_ahub.h"
55#include "tegra30_i2s.h"
56#include "tegra30_dam.h"
57#endif
58
59
60#define DRV_NAME "tegra-snd-aic326x"
61
62#define GPIO_SPKR_EN BIT(0)
63#define GPIO_HP_MUTE BIT(1)
64#define GPIO_INT_MIC_EN BIT(2)
65#define GPIO_EXT_MIC_EN BIT(3)
66
67#define DAI_LINK_HIFI 0
68#define DAI_LINK_SPDIF 1
69#define DAI_LINK_BTSCO 2
70#define DAI_LINK_VOICE_CALL 3
71#define DAI_LINK_BT_VOICE_CALL 4
72#define NUM_DAI_LINKS 5
73
74extern int g_is_call_mode;
75
76#ifndef CONFIG_ARCH_TEGRA_2x_SOC
77const char *tegra_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
78 "tegra30-i2s.0",
79 "tegra30-i2s.1",
80 "tegra30-i2s.2",
81 "tegra30-i2s.3",
82 "tegra30-i2s.4",
83};
84#endif
85
86struct tegra_aic326x {
87 struct tegra_asoc_utils_data util_data;
88 struct tegra_aic326x_platform_data *pdata;
89 struct regulator *audio_reg;
90 int gpio_requested;
91 bool init_done;
92 int is_call_mode;
93 int is_device_bt;
94#ifndef CONFIG_ARCH_TEGRA_2x_SOC
95 struct codec_config codec_info[NUM_I2S_DEVICES];
96 struct snd_soc_card *pcard;
97#endif
98};
99
100static int tegra_aic326x_call_mode_info(struct snd_kcontrol *kcontrol,
101 struct snd_ctl_elem_info *uinfo)
102{
103 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
104 uinfo->count = 1;
105 uinfo->value.integer.min = 0;
106 uinfo->value.integer.max = 1;
107 return 0;
108}
109
110static int tegra_aic326x_call_mode_get(struct snd_kcontrol *kcontrol,
111 struct snd_ctl_elem_value *ucontrol)
112{
113 struct tegra_aic326x *machine = snd_kcontrol_chip(kcontrol);
114
115 ucontrol->value.integer.value[0] = machine->is_call_mode;
116
117 return 0;
118}
119
120static int tegra_aic326x_call_mode_put(struct snd_kcontrol *kcontrol,
121 struct snd_ctl_elem_value *ucontrol)
122{
123 struct tegra_aic326x *machine = snd_kcontrol_chip(kcontrol);
124 int is_call_mode_new = ucontrol->value.integer.value[0];
125#ifdef CONFIG_ARCH_TEGRA_2x_SOC
126 int codec_dap_id, codec_dap_sel, bb_dap_id, bb_dap_sel;
127#else /*assumes tegra3*/
128 int codec_index;
129 unsigned int i;
130#endif
131
132 if (machine->is_call_mode == is_call_mode_new)
133 return 0;
134
135#ifdef CONFIG_ARCH_TEGRA_2x_SOC
136 bb_dap_id = TEGRA20_DAS_DAP_ID_3;
137 bb_dap_sel = TEGRA20_DAS_DAP_SEL_DAP3;
138
139 if (machine->is_device_bt) {
140 codec_dap_id = TEGRA20_DAS_DAP_ID_4;
141 codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP4;
142 }
143 else {
144 codec_dap_id = TEGRA20_DAS_DAP_ID_2;
145 codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP2;
146 }
147#else /*assumes tegra3*/
148 if (machine->is_device_bt)
149 codec_index = BT_SCO;
150 else
151 codec_index = HIFI_CODEC;
152#endif
153
154 if (is_call_mode_new) {
155#ifdef CONFIG_ARCH_TEGRA_2x_SOC
156 tegra20_das_set_tristate(codec_dap_id, 1);
157 tegra20_das_set_tristate(bb_dap_id, 1);
158 tegra20_das_connect_dap_to_dap(codec_dap_id,
159 bb_dap_sel, 0, 0, 0);
160 tegra20_das_connect_dap_to_dap(bb_dap_id,
161 codec_dap_sel, 1, 0, 0);
162 tegra20_das_set_tristate(codec_dap_id, 0);
163 tegra20_das_set_tristate(bb_dap_id, 0);
164#else /*assumes tegra3*/
165 if (machine->codec_info[codec_index].rate == 0 ||
166 machine->codec_info[codec_index].channels == 0)
167 return -EINVAL;
168
169 for (i = 0; i < machine->pcard->num_links; i++)
170 machine->pcard->dai_link[i].ignore_suspend = 1;
171
172 tegra30_make_voice_call_connections(
173 &machine->codec_info[codec_index],
174 &machine->codec_info[BASEBAND]);
175#endif
176 } else {
177#ifdef CONFIG_ARCH_TEGRA_2x_SOC
178 tegra20_das_set_tristate(codec_dap_id, 1);
179 tegra20_das_set_tristate(bb_dap_id, 1);
180 tegra20_das_connect_dap_to_dap(bb_dap_id,
181 bb_dap_sel, 0, 0, 0);
182 tegra20_das_connect_dap_to_dap(codec_dap_id,
183 codec_dap_sel, 0, 0, 0);
184 tegra20_das_set_tristate(codec_dap_id, 0);
185 tegra20_das_set_tristate(bb_dap_id, 0);
186#else /*assumes tegra3*/
187 tegra30_break_voice_call_connections(
188 &machine->codec_info[codec_index],
189 &machine->codec_info[BASEBAND]);
190
191 for (i = 0; i < machine->pcard->num_links; i++)
192 machine->pcard->dai_link[i].ignore_suspend = 0;
193#endif
194 }
195
196 machine->is_call_mode = is_call_mode_new;
197 g_is_call_mode = machine->is_call_mode;
198
199 return 1;
200}
201
202struct snd_kcontrol_new tegra_aic326x_call_mode_control = {
203 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
204 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
205 .name = "Call Mode Switch",
206 .private_value = 0xffff,
207 .info = tegra_aic326x_call_mode_info,
208 .get = tegra_aic326x_call_mode_get,
209 .put = tegra_aic326x_call_mode_put
210};
211
212static int tegra_aic326x_get_mclk(int srate)
213{
214 int mclk = 0;
215 switch (srate) {
216 case 8000:
217 case 16000:
218 case 24000:
219 case 32000:
220 case 48000:
221 case 64000:
222 case 96000:
223 mclk = 12288000;
224 break;
225 case 11025:
226 case 22050:
227 case 44100:
228 case 88200:
229 mclk = 11289600;
230 break;
231 default:
232 mclk = -EINVAL;
233 break;
234 }
235
236 return mclk;
237}
238
239#ifndef CONFIG_ARCH_TEGRA_2x_SOC
240static int tegra_aic326x_set_dam_cif(int dam_ifc, int srate,
241 int channels, int bit_size, int src_on, int src_srate,
242 int src_channels, int src_bit_size)
243{
244 tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
245 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHOUT,
246 srate);
247 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN1,
248 srate);
249 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN1,
250 channels, bit_size, channels,
251 bit_size);
252 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHOUT,
253 channels, bit_size, channels,
254 bit_size);
255
256 if (src_on) {
257 tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN0_SRC, 0x1000);
258 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
259 src_srate);
260 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
261 src_channels, src_bit_size, 1, 16);
262 }
263
264 return 0;
265}
266#endif
267
268static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream,
269 struct snd_pcm_hw_params *params)
270{
271 struct snd_soc_pcm_runtime *rtd = substream->private_data;
272 struct snd_soc_dai *codec_dai = rtd->codec_dai;
273 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
274 struct snd_soc_codec *codec = rtd->codec;
275 struct snd_soc_card *card = codec->card;
276 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
277 int srate, mclk, sample_size, daifmt;
278 int err;
279#ifndef CONFIG_ARCH_TEGRA_2x_SOC
280 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
281#endif
282
283 switch (params_format(params)) {
284 case SNDRV_PCM_FORMAT_S16_LE:
285 sample_size = 16;
286 break;
287 default:
288 return -EINVAL;
289 }
290
291 srate = params_rate(params);
292
293 mclk = tegra_aic326x_get_mclk(srate);
294 if (mclk < 0)
295 return mclk;
296
297 daifmt = SND_SOC_DAIFMT_I2S |
298 SND_SOC_DAIFMT_NB_NF |
299 SND_SOC_DAIFMT_CBS_CFS;
300
301 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
302 if (err < 0) {
303 if (!(machine->util_data.set_mclk % mclk))
304 mclk = machine->util_data.set_mclk;
305 else {
306 dev_err(card->dev, "Can't configure clocks\n");
307 return err;
308 }
309 }
310
311 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
312
313 err = snd_soc_dai_set_fmt(codec_dai, daifmt);
314 if (err < 0) {
315 dev_err(card->dev, "codec_dai fmt not set\n");
316 return err;
317 }
318
319 err = snd_soc_dai_set_fmt(cpu_dai, daifmt);
320 if (err < 0) {
321 dev_err(card->dev, "cpu_dai fmt not set\n");
322 return err;
323 }
324
325 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
326 SND_SOC_CLOCK_IN);
327 if (err < 0) {
328 dev_err(card->dev, "codec_dai clock not set\n");
329 return err;
330 }
331
332#ifdef CONFIG_ARCH_TEGRA_2x_SOC
333 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
334 TEGRA20_DAS_DAP_ID_1);
335 if (err < 0) {
336 dev_err(card->dev, "failed to set dap-dac path\n");
337 return err;
338 }
339
340 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
341 TEGRA20_DAS_DAP_SEL_DAC1);
342 if (err < 0) {
343 dev_err(card->dev, "failed to set dac-dap path\n");
344 return err;
345 }
346#else /*assumes tegra3*/
347 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s->is_dam_used)
348 tegra_aic326x_set_dam_cif(i2s->dam_ifc, srate,
349 params_channels(params), sample_size, 0, 0, 0, 0);
350#endif
351
352 return 0;
353}
354
355static int tegra_aic326x_spdif_hw_params(struct snd_pcm_substream *substream,
356 struct snd_pcm_hw_params *params)
357{
358 struct snd_soc_pcm_runtime *rtd = substream->private_data;
359 struct snd_soc_card *card = rtd->card;
360 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
361 int srate, mclk, min_mclk;
362 int err;
363
364 srate = params_rate(params);
365
366 mclk = tegra_aic326x_get_mclk(srate);
367 if (mclk < 0)
368 return mclk;
369
370 min_mclk = 128 * srate;
371
372 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
373 if (err < 0) {
374 if (!(machine->util_data.set_mclk % min_mclk))
375 mclk = machine->util_data.set_mclk;
376 else {
377 dev_err(card->dev, "Can't configure clocks\n");
378 return err;
379 }
380 }
381
382 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
383
384 return 0;
385}
386
387static int tegra_aic326x_bt_hw_params(struct snd_pcm_substream *substream,
388 struct snd_pcm_hw_params *params)
389{
390 struct snd_soc_pcm_runtime *rtd = substream->private_data;
391 struct snd_soc_card *card = rtd->card;
392 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
393 int err, srate, mclk, min_mclk, sample_size;
394#ifndef CONFIG_ARCH_TEGRA_2x_SOC
395 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
396#endif
397
398 switch (params_format(params)) {
399 case SNDRV_PCM_FORMAT_S16_LE:
400 sample_size = 16;
401 break;
402 default:
403 return -EINVAL;
404 }
405
406 srate = params_rate(params);
407
408 mclk = tegra_aic326x_get_mclk(srate);
409 if (mclk < 0)
410 return mclk;
411
412 min_mclk = 64 * srate;
413
414 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
415 if (err < 0) {
416 if (!(machine->util_data.set_mclk % min_mclk))
417 mclk = machine->util_data.set_mclk;
418 else {
419 dev_err(card->dev, "Can't configure clocks\n");
420 return err;
421 }
422 }
423
424 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
425
426 err = snd_soc_dai_set_fmt(rtd->cpu_dai,
427 SND_SOC_DAIFMT_DSP_A |
428 SND_SOC_DAIFMT_NB_NF |
429 SND_SOC_DAIFMT_CBS_CFS);
430
431 if (err < 0) {
432 dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
433 return err;
434 }
435
436#ifdef CONFIG_ARCH_TEGRA_2x_SOC
437 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
438 TEGRA20_DAS_DAP_ID_4);
439 if (err < 0) {
440 dev_err(card->dev, "failed to set dac-dap path\n");
441 return err;
442 }
443
444 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
445 TEGRA20_DAS_DAP_SEL_DAC2);
446 if (err < 0) {
447 dev_err(card->dev, "failed to set dac-dap path\n");
448 return err;
449 }
450#else
451 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s->is_dam_used)
452 tegra_aic326x_set_dam_cif(i2s->dam_ifc, params_rate(params),
453 params_channels(params), sample_size, 0, 0, 0, 0);
454#endif
455
456 return 0;
457}
458
459#ifndef CONFIG_ARCH_TEGRA_2x_SOC
460static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
461{
462 struct snd_soc_pcm_runtime *rtd = substream->private_data;
463 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
464 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
465 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(rtd->card);
466 struct codec_config *codec_info;
467 struct codec_config *bb_info;
468 int codec_index;
469
470 if (!i2s->is_dam_used)
471 return 0;
472
473 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
474 /*dam configuration*/
475 if (!i2s->dam_ch_refcount)
476 i2s->dam_ifc = tegra30_dam_allocate_controller();
477
478 tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
479 i2s->dam_ch_refcount++;
480 tegra30_dam_enable_clock(i2s->dam_ifc);
481
482 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
483 (i2s->dam_ifc*2), i2s->txcif);
484
485 /*
486 *make the dam tx to i2s rx connection if this is the only client
487 *using i2s for playback
488 */
489 if (i2s->playback_ref_count == 1)
490 tegra30_ahub_set_rx_cif_source(
491 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
492 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
493
494 /* enable the dam*/
495 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
496 TEGRA30_DAM_CHIN1);
497 } else {
498
499 i2s->is_call_mode_rec = machine->is_call_mode;
500
501 if (!i2s->is_call_mode_rec)
502 return 0;
503
504 if (machine->is_device_bt)
505 codec_index = BT_SCO;
506 else
507 codec_index = HIFI_CODEC;
508
509 codec_info = &machine->codec_info[codec_index];
510 bb_info = &machine->codec_info[BASEBAND];
511
512 /* allocate a dam for voice call recording */
513
514 i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();
515 tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
516 TEGRA30_DAM_CHIN0_SRC);
517 tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
518 TEGRA30_DAM_CHIN1);
519 tegra30_dam_enable_clock(i2s->call_record_dam_ifc);
520
521 /* configure the dam */
522 tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc,
523 codec_info->rate, codec_info->channels,
524 codec_info->bitsize, 1, bb_info->rate,
525 bb_info->channels, bb_info->bitsize);
526
527 /* setup the connections for voice call record */
528
529 tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
530 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
531 (i2s->call_record_dam_ifc*2),
532 TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
533 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
534 (i2s->call_record_dam_ifc*2),
535 TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
536 tegra30_ahub_set_rx_cif_source(i2s->rxcif,
537 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
538
539 /* enable the dam*/
540
541 tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
542 TEGRA30_DAM_CHIN1);
543 tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
544 TEGRA30_DAM_CHIN0_SRC);
545 }
546
547 return 0;
548}
549
550static void tegra_aic326x_shutdown(struct snd_pcm_substream *substream)
551{
552 struct snd_soc_pcm_runtime *rtd = substream->private_data;
553 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
554 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
555
556 if (!i2s->is_dam_used)
557 return;
558
559 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
560 /* disable the dam*/
561 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
562 TEGRA30_DAM_CHIN1);
563
564 /* disconnect the ahub connections*/
565 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
566 (i2s->dam_ifc*2));
567
568 /* disable the dam and free the controller */
569 tegra30_dam_disable_clock(i2s->dam_ifc);
570 tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
571 i2s->dam_ch_refcount--;
572 if (!i2s->dam_ch_refcount)
573 tegra30_dam_free_controller(i2s->dam_ifc);
574 } else {
575
576 if (!i2s->is_call_mode_rec)
577 return 0;
578
579 i2s->is_call_mode_rec = 0;
580
581 /* disable the dam*/
582 tegra30_dam_enable(i2s->call_record_dam_ifc,
583 TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
584 tegra30_dam_enable(i2s->call_record_dam_ifc,
585 TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
586
587 /* disconnect the ahub connections*/
588 tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
589 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
590 (i2s->call_record_dam_ifc*2));
591 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
592 (i2s->call_record_dam_ifc*2));
593
594 /* free the dam channels and dam controller */
595 tegra30_dam_disable_clock(i2s->call_record_dam_ifc);
596 tegra30_dam_free_channel(i2s->call_record_dam_ifc,
597 TEGRA30_DAM_CHIN1);
598 tegra30_dam_free_channel(i2s->call_record_dam_ifc,
599 TEGRA30_DAM_CHIN0_SRC);
600 tegra30_dam_free_controller(i2s->call_record_dam_ifc);
601 }
602
603 return;
604}
605#endif
606
607
608static int tegra_aic326x_hw_free(struct snd_pcm_substream *substream)
609{
610 struct snd_soc_pcm_runtime *rtd = substream->private_data;
611 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(rtd->card);
612
613 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
614
615 return 0;
616}
617
618static int tegra_aic326x_voice_call_hw_params(
619 struct snd_pcm_substream *substream,
620 struct snd_pcm_hw_params *params)
621{
622 struct snd_soc_pcm_runtime *rtd = substream->private_data;
623 struct snd_soc_dai *codec_dai = rtd->codec_dai;
624 struct snd_soc_codec *codec = rtd->codec;
625 struct snd_soc_card *card = codec->card;
626 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
627 int srate, mclk;
628 int err, pcmdiv, vxclkdiv;;
629
630 srate = params_rate(params);
631 mclk = tegra_aic326x_get_mclk(srate);
632 if (mclk < 0)
633 return mclk;
634
635 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
636 if (err < 0) {
637 if (!(machine->util_data.set_mclk % mclk))
638 mclk = machine->util_data.set_mclk;
639 else {
640 dev_err(card->dev, "Can't configure clocks\n");
641 return err;
642 }
643 }
644
645 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
646
647 if(machine_is_tegra_enterprise()) {
648 err = snd_soc_dai_set_fmt(codec_dai,
649 SND_SOC_DAIFMT_I2S |
650 SND_SOC_DAIFMT_NB_NF |
651 SND_SOC_DAIFMT_CBS_CFS);
652 } else {
653 err = snd_soc_dai_set_fmt(codec_dai,
654 SND_SOC_DAIFMT_DSP_B |
655 SND_SOC_DAIFMT_NB_NF |
656 SND_SOC_DAIFMT_CBS_CFS);
657 }
658
659 if (err < 0) {
660 dev_err(card->dev, "codec_dai fmt not set\n");
661 return err;
662 }
663
664 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
665 SND_SOC_CLOCK_IN);
666 if (err < 0) {
667 dev_err(card->dev, "codec_dai clock not set\n");
668 return err;
669 }
670
671 if(!machine_is_tegra_enterprise()) {
672 if (params_rate(params) == 8000) {
673 /* Change these Settings for 8KHz*/
674 pcmdiv = 1;
675 /* BB expecting 2048Khz bclk */
676 vxclkdiv = 27;
677 } else if (params_rate(params) == 16000) {
678 pcmdiv = 1;
679 /* BB expecting 2048Khz bclk */
680 vxclkdiv = 27;
681 } else {
682 dev_err(card->dev, "codec_dai unsupported voice rate\n");
683 return -EINVAL;
684 }
685 }
686
687 //snd_soc_dai_set_clkdiv(codec_dai, ASI2_BCLK_N, vxclkdiv);
688 //snd_soc_dai_set_clkdiv(codec_dai, ASI2_WCLK_N, pcmdiv);
689
690#ifndef CONFIG_ARCH_TEGRA_2x_SOC
691 /* codec configuration */
692 machine->codec_info[HIFI_CODEC].rate = params_rate(params);
693 machine->codec_info[HIFI_CODEC].channels = params_channels(params);
694 machine->codec_info[HIFI_CODEC].bitsize = 16;
695 machine->codec_info[HIFI_CODEC].is_i2smaster = 1;
696 machine->codec_info[HIFI_CODEC].is_format_dsp = 0;
697
698 /* baseband configuration */
699 machine->codec_info[BASEBAND].bitsize = 16;
700 machine->codec_info[BASEBAND].is_i2smaster = 1;
701 machine->codec_info[BASEBAND].is_format_dsp = 1;
702#endif
703
704 machine->is_device_bt = 0;
705
706 return 0;
707}
708
709static void tegra_aic326x_voice_call_shutdown(
710 struct snd_pcm_substream *substream)
711{
712 struct snd_soc_pcm_runtime *rtd = substream->private_data;
713 struct tegra_aic326x *machine =
714 snd_soc_card_get_drvdata(rtd->codec->card);
715
716#ifndef CONFIG_ARCH_TEGRA_2x_SOC
717 machine->codec_info[HIFI_CODEC].rate = 0;
718 machine->codec_info[HIFI_CODEC].channels = 0;
719#endif
720
721 machine->is_device_bt = 0;
722}
723
724static int tegra_aic326x_bt_voice_call_hw_params(
725 struct snd_pcm_substream *substream,
726 struct snd_pcm_hw_params *params)
727{
728 struct snd_soc_pcm_runtime *rtd = substream->private_data;
729 struct snd_soc_card *card = rtd->card;
730 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
731 int err, srate, mclk, min_mclk;
732
733 srate = params_rate(params);
734
735 mclk = tegra_aic326x_get_mclk(srate);
736 if (mclk < 0)
737 return mclk;
738
739 min_mclk = 64 * srate;
740
741 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
742 if (err < 0) {
743 if (!(machine->util_data.set_mclk % min_mclk))
744 mclk = machine->util_data.set_mclk;
745 else {
746 dev_err(card->dev, "Can't configure clocks\n");
747 return err;
748 }
749 }
750
751 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
752
753#ifndef CONFIG_ARCH_TEGRA_2x_SOC
754 /* codec configuration */
755 machine->codec_info[BT_SCO].rate = params_rate(params);
756 machine->codec_info[BT_SCO].channels = params_channels(params);
757 machine->codec_info[BT_SCO].bitsize = 16;
758 machine->codec_info[BT_SCO].is_i2smaster = 1;
759 machine->codec_info[BT_SCO].is_format_dsp = 1;
760
761 /* baseband configuration */
762 machine->codec_info[BASEBAND].bitsize = 16;
763 machine->codec_info[BASEBAND].is_i2smaster = 1;
764 machine->codec_info[BASEBAND].is_format_dsp = 1;
765#endif
766
767 machine->is_device_bt = 1;
768
769 return 0;
770}
771
772static void tegra_aic326x_bt_voice_call_shutdown(
773 struct snd_pcm_substream *substream)
774{
775 struct snd_soc_pcm_runtime *rtd = substream->private_data;
776 struct tegra_aic326x *machine =
777 snd_soc_card_get_drvdata(rtd->codec->card);
778
779#ifndef CONFIG_ARCH_TEGRA_2x_SOC
780 machine->codec_info[BT_SCO].rate = 0;
781 machine->codec_info[BT_SCO].channels = 0;
782#endif
783
784 machine->is_device_bt = 0;
785}
786
787static struct snd_soc_ops tegra_aic326x_hifi_ops = {
788 .hw_params = tegra_aic326x_hw_params,
789 .hw_free = tegra_aic326x_hw_free,
790#ifndef CONFIG_ARCH_TEGRA_2x_SOC
791 .startup = tegra_aic326x_startup,
792 .shutdown = tegra_aic326x_shutdown,
793#endif
794};
795
796static struct snd_soc_ops tegra_aic326x_spdif_ops = {
797 .hw_params = tegra_aic326x_spdif_hw_params,
798 .hw_free = tegra_aic326x_hw_free,
799};
800
801static struct snd_soc_ops tegra_aic326x_voice_call_ops = {
802 .hw_params = tegra_aic326x_voice_call_hw_params,
803 .shutdown = tegra_aic326x_voice_call_shutdown,
804 .hw_free = tegra_aic326x_hw_free,
805};
806
807static struct snd_soc_ops tegra_aic326x_bt_voice_call_ops = {
808 .hw_params = tegra_aic326x_bt_voice_call_hw_params,
809 .shutdown = tegra_aic326x_bt_voice_call_shutdown,
810 .hw_free = tegra_aic326x_hw_free,
811};
812
813static struct snd_soc_ops tegra_aic326x_bt_ops = {
814 .hw_params = tegra_aic326x_bt_hw_params,
815 .hw_free = tegra_aic326x_hw_free,
816#ifndef CONFIG_ARCH_TEGRA_2x_SOC
817 .startup = tegra_aic326x_startup,
818 .shutdown = tegra_aic326x_shutdown,
819#endif
820};
821
822static struct snd_soc_jack tegra_aic326x_hp_jack;
823
824#ifdef CONFIG_SWITCH
825static struct switch_dev aic326x_wired_switch_dev = {
826 .name = "h2w",
827};
828
829/* These values are copied from WiredAccessoryObserver */
830enum headset_state {
831 BIT_NO_HEADSET = 0,
832 BIT_HEADSET = (1 << 0),
833 BIT_HEADSET_NO_MIC = (1 << 1),
834};
835
836static int aic326x_headset_switch_notify(struct notifier_block *self,
837 unsigned long action, void *dev)
838{
839 int state = 0;
840
841 switch (action) {
842 case SND_JACK_HEADPHONE:
843 state |= BIT_HEADSET_NO_MIC;
844 break;
845 case SND_JACK_HEADSET:
846 state |= BIT_HEADSET;
847 break;
848 default:
849 state |= BIT_NO_HEADSET;
850 }
851
852 switch_set_state(&aic326x_wired_switch_dev, state);
853
854 return NOTIFY_OK;
855}
856
857static struct notifier_block aic326x_headset_switch_nb = {
858 .notifier_call = aic326x_headset_switch_notify,
859};
860#else
861static struct snd_soc_jack_pin tegra_aic326x_hp_jack_pins[] = {
862 {
863 .pin = "Headphone Jack",
864 .mask = SND_JACK_HEADPHONE,
865 },
866};
867#endif
868
869static int tegra_aic326x_event_int_spk(struct snd_soc_dapm_widget *w,
870 struct snd_kcontrol *k, int event)
871{
872 struct snd_soc_dapm_context *dapm = w->dapm;
873 struct snd_soc_card *card = dapm->card;
874 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
875 struct tegra_aic326x_platform_data *pdata = machine->pdata;
876
877 if (!(machine->gpio_requested & GPIO_SPKR_EN))
878 return 0;
879
880 gpio_set_value_cansleep(pdata->gpio_spkr_en,
881 SND_SOC_DAPM_EVENT_ON(event));
882
883 return 0;
884}
885
886static int tegra_aic326x_event_hp(struct snd_soc_dapm_widget *w,
887 struct snd_kcontrol *k, int event)
888{
889 struct snd_soc_dapm_context *dapm = w->dapm;
890 struct snd_soc_card *card = dapm->card;
891 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
892 struct tegra_aic326x_platform_data *pdata = machine->pdata;
893
894 if (!(machine->gpio_requested & GPIO_HP_MUTE))
895 return 0;
896
897 gpio_set_value_cansleep(pdata->gpio_hp_mute,
898 !SND_SOC_DAPM_EVENT_ON(event));
899
900 return 0;
901}
902
903static const struct snd_soc_dapm_widget tegra_aic326x_dapm_widgets[] = {
904 SND_SOC_DAPM_SPK("Int Spk", tegra_aic326x_event_int_spk),
905 SND_SOC_DAPM_HP("Earpiece", NULL),
906 SND_SOC_DAPM_HP("Headphone Jack", tegra_aic326x_event_hp),
907 SND_SOC_DAPM_MIC("Mic Jack", NULL),
908 SND_SOC_DAPM_INPUT("Ext Mic"),
909 SND_SOC_DAPM_LINE("Linein", NULL),
910 SND_SOC_DAPM_MIC("Int Mic", NULL),
911};
912
913static const struct snd_soc_dapm_route aic326x_audio_map[] = {
914 {"Int Spk", NULL, "SPKL"},
915 {"Int Spk", NULL, "SPKR"},
916 {"Earpiece", NULL, "RECP"},
917 {"Earpiece", NULL, "RECM"},
918 {"Headphone Jack", NULL, "HPL"},
919 {"Headphone Jack", NULL, "HPR"},
920 /* internal (IN2L/IN2R) mic is stero */
921 {"Mic Bias Int" ,NULL, "Int Mic"},
922 {"IN2L", NULL, "Mic Bias Int"},
923 {"Mic Bias Int" ,NULL, "Int Mic"},
924 {"IN2R", NULL, "Mic Bias Int"},
925 {"Mic Bias Ext" ,NULL, "Mic Jack"},
926 {"CM1L" ,NULL, "Mic Jack"},
927 {"IN1L", NULL, "Mic Bias Ext"},
928 {"IN1L", NULL, "CM1L"},
929};
930
931static const struct snd_kcontrol_new tegra_aic326x_controls[] = {
932 SOC_DAPM_PIN_SWITCH("Int Spk"),
933 SOC_DAPM_PIN_SWITCH("Earpiece"),
934 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
935 SOC_DAPM_PIN_SWITCH("Mic Jack"),
936 SOC_DAPM_PIN_SWITCH("Ext Mic"),
937 SOC_DAPM_PIN_SWITCH("Linein"),
938 SOC_DAPM_PIN_SWITCH("Int Mic"),
939};
940
941static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
942{
943 struct snd_soc_codec *codec = rtd->codec;
944 struct snd_soc_dapm_context *dapm = &codec->dapm;
945 struct snd_soc_card *card = codec->card;
946 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
947 struct tegra_aic326x_platform_data *pdata = machine->pdata;
948#ifndef CONFIG_ARCH_TEGRA_2x_SOC
949 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
950#endif
951 int ret;
952
953#ifndef CONFIG_ARCH_TEGRA_2x_SOC
954 if (machine->codec_info[BASEBAND].i2s_id != -1)
955 i2s->is_dam_used = true;
956#endif
957
958 if (machine->init_done)
959 return 0;
960
961 machine->init_done = true;
962
963#ifndef CONFIG_ARCH_TEGRA_2x_SOC
964 machine->pcard = card;
965#endif
966
967 if (machine_is_whistler()) {
968 machine->audio_reg = regulator_get(NULL, "avddio_audio");
969 if (IS_ERR(machine->audio_reg)) {
970 dev_err(card->dev, "cannot get avddio_audio reg\n");
971 ret = PTR_ERR(machine->audio_reg);
972 return ret;
973 }
974
975 ret = regulator_enable(machine->audio_reg);
976 if (ret) {
977 dev_err(card->dev, "cannot enable avddio_audio reg\n");
978 regulator_put(machine->audio_reg);
979 machine->audio_reg = NULL;
980 return ret;
981 }
982 }
983
984 if (gpio_is_valid(pdata->gpio_spkr_en)) {
985 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
986 if (ret) {
987 dev_err(card->dev, "cannot get spkr_en gpio\n");
988 return ret;
989 }
990 machine->gpio_requested |= GPIO_SPKR_EN;
991
992 gpio_direction_output(pdata->gpio_spkr_en, 0);
993 }
994
995 if (gpio_is_valid(pdata->gpio_hp_mute)) {
996 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
997 if (ret) {
998 dev_err(card->dev, "cannot get hp_mute gpio\n");
999 return ret;
1000 }
1001 machine->gpio_requested |= GPIO_HP_MUTE;
1002
1003 gpio_direction_output(pdata->gpio_hp_mute, 0);
1004 }
1005
1006 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
1007 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
1008 if (ret) {
1009 dev_err(card->dev, "cannot get int_mic_en gpio\n");
1010 return ret;
1011 }
1012 machine->gpio_requested |= GPIO_INT_MIC_EN;
1013
1014 /* Disable int mic; enable signal is active-high */
1015 gpio_direction_output(pdata->gpio_int_mic_en, 0);
1016 }
1017
1018 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
1019 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
1020 if (ret) {
1021 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
1022 return ret;
1023 }
1024 machine->gpio_requested |= GPIO_EXT_MIC_EN;
1025
1026 /* Enable ext mic; enable signal is active-low */
1027 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
1028 }
1029
1030 ret = snd_soc_add_controls(codec, tegra_aic326x_controls,
1031 ARRAY_SIZE(tegra_aic326x_controls));
1032 if (ret < 0)
1033 return ret;
1034
1035 snd_soc_dapm_new_controls(dapm, tegra_aic326x_dapm_widgets,
1036 ARRAY_SIZE(tegra_aic326x_dapm_widgets));
1037
1038 snd_soc_dapm_add_routes(dapm, aic326x_audio_map,
1039 ARRAY_SIZE(aic326x_audio_map));
1040
1041 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
1042 &tegra_aic326x_hp_jack);
1043 if (ret < 0)
1044 return ret;
1045
1046#ifdef CONFIG_SWITCH
1047 snd_soc_jack_notifier_register(&tegra_aic326x_hp_jack,
1048 &aic326x_headset_switch_nb);
1049#else /*gpio based headset detection*/
1050 snd_soc_jack_add_pins(&tegra_aic326x_hp_jack,
1051 ARRAY_SIZE(tegra_aic326x_hp_jack_pins),
1052 tegra_aic326x_hp_jack_pins);
1053#endif
1054
1055 aic326x_headset_detect(codec, &tegra_aic326x_hp_jack,
1056 SND_JACK_HEADSET);
1057
1058 /* Add call mode switch control */
1059 ret = snd_ctl_add(codec->card->snd_card,
1060 snd_ctl_new1(&tegra_aic326x_call_mode_control,
1061 machine));
1062 if (ret < 0)
1063 return ret;
1064
1065 snd_soc_dapm_force_enable_pin(dapm, "MICBIAS_EXT ON");
1066 snd_soc_dapm_force_enable_pin(dapm,"MICBIAS_INT ON");
1067 snd_soc_dapm_sync(dapm);
1068
1069 return 0;
1070}
1071
1072static struct snd_soc_dai_link tegra_aic326x_dai[] = {
1073 [DAI_LINK_HIFI] = {
1074 .name = "AIC3262",
1075 .stream_name = "AIC3262 PCM HIFI",
1076 .codec_name = "aic3262-codec.4-0018",
1077 .platform_name = "tegra-pcm-audio",
1078#ifdef CONFIG_ARCH_TEGRA_2x_SOC
1079 .cpu_dai_name = "tegra20-i2s.0",
1080#else
1081 .cpu_dai_name = "tegra30-i2s.0",
1082#endif
1083 .codec_dai_name = "aic3262-asi1",
1084 .init = tegra_aic326x_init,
1085 .ops = &tegra_aic326x_hifi_ops,
1086 },
1087 [DAI_LINK_SPDIF] = {
1088 .name = "SPDIF",
1089 .stream_name = "SPDIF PCM",
1090 .codec_name = "spdif-dit.0",
1091 .platform_name = "tegra-pcm-audio",
1092#ifdef CONFIG_ARCH_TEGRA_2x_SOC
1093 .cpu_dai_name = "tegra20-spdif",
1094#else
1095 .cpu_dai_name = "tegra30-spdif",
1096#endif
1097 .codec_dai_name = "dit-hifi",
1098 .ops = &tegra_aic326x_spdif_ops,
1099 },
1100 [DAI_LINK_BTSCO] = {
1101 .name = "BT-SCO",
1102 .stream_name = "BT SCO PCM",
1103 .codec_name = "spdif-dit.1",
1104 .platform_name = "tegra-pcm-audio",
1105#ifdef CONFIG_ARCH_TEGRA_2x_SOC
1106 .cpu_dai_name = "tegra20-i2s.1",
1107#else
1108 .cpu_dai_name = "tegra30-i2s.3",
1109#endif
1110 .codec_dai_name = "dit-hifi",
1111 .init = tegra_aic326x_init,
1112 .ops = &tegra_aic326x_bt_ops,
1113 },
1114 [DAI_LINK_VOICE_CALL] = {
1115 .name = "VOICE CALL",
1116 .stream_name = "VOICE CALL PCM",
1117 .codec_name = "aic3262-codec.4-0018",
1118 .platform_name = "tegra-pcm-audio",
1119 .cpu_dai_name = "dit-hifi",
1120 .codec_dai_name = "aic3262-asi2",
1121 .ops = &tegra_aic326x_voice_call_ops,
1122 },
1123 [DAI_LINK_BT_VOICE_CALL] = {
1124 .name = "BT VOICE CALL",
1125 .stream_name = "BT VOICE CALL PCM",
1126 .codec_name = "spdif-dit.2",
1127 .platform_name = "tegra-pcm-audio",
1128 .cpu_dai_name = "dit-hifi",
1129 .codec_dai_name = "dit-hifi",
1130 .ops = &tegra_aic326x_bt_voice_call_ops,
1131 },
1132};
1133
1134static struct snd_soc_card snd_soc_tegra_aic326x = {
1135 .name = "tegra-aic326x",
1136 .dai_link = tegra_aic326x_dai,
1137 .num_links = ARRAY_SIZE(tegra_aic326x_dai),
1138};
1139
1140static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
1141{
1142 struct snd_soc_card *card = &snd_soc_tegra_aic326x;
1143 struct tegra_aic326x *machine;
1144 struct tegra_aic326x_platform_data *pdata;
1145 int ret, i;
1146
1147 pdata = pdev->dev.platform_data;
1148 if (!pdata) {
1149 dev_err(&pdev->dev, "No platform data supplied\n");
1150 return -EINVAL;
1151 }
1152
1153 machine = kzalloc(sizeof(struct tegra_aic326x), GFP_KERNEL);
1154 if (!machine) {
1155 dev_err(&pdev->dev, "Can't allocate tegra_aic326x struct\n");
1156 return -ENOMEM;
1157 }
1158
1159 machine->pdata = pdata;
1160
1161 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
1162 if (ret)
1163 goto err_free_machine;
1164
1165 card->dev = &pdev->dev;
1166 platform_set_drvdata(pdev, card);
1167 snd_soc_card_set_drvdata(card, machine);
1168
1169#ifdef CONFIG_SWITCH
1170 /* Add h2w switch class support */
1171 ret = switch_dev_register(&aic326x_wired_switch_dev);
1172 if (ret < 0) {
1173 dev_err(&pdev->dev, "not able to register switch device %d\n",
1174 ret);
1175 goto err_fini_utils;
1176 }
1177#endif
1178
1179#ifndef CONFIG_ARCH_TEGRA_2x_SOC
1180 for (i = 0; i < NUM_I2S_DEVICES ; i++)
1181 machine->codec_info[i].i2s_id = pdata->audio_port_id[i];
1182
1183 machine->codec_info[BASEBAND].rate = pdata->baseband_param.rate;
1184 machine->codec_info[BASEBAND].channels = pdata->baseband_param.channels;
1185
1186 tegra_aic326x_dai[DAI_LINK_HIFI].cpu_dai_name =
1187 tegra_i2s_dai_name[machine->codec_info[HIFI_CODEC].i2s_id];
1188
1189 tegra_aic326x_dai[DAI_LINK_BTSCO].cpu_dai_name =
1190 tegra_i2s_dai_name[machine->codec_info[BT_SCO].i2s_id];
1191#endif
1192
1193 if(machine_is_tegra_enterprise()) {
1194 tegra_aic326x_dai[DAI_LINK_HIFI].codec_name = "aic3262-codec.0-0018";
1195 tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_name = "aic3262-codec.0-0018";
1196 tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_dai_name = "aic3262-asi1";
1197 }
1198
1199 ret = snd_soc_register_card(card);
1200 if (ret) {
1201 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
1202 ret);
1203 goto err_switch_unregister;
1204 }
1205
1206 if (!card->instantiated) {
1207 dev_err(&pdev->dev, "No TI AIC3262 codec\n");
1208 goto err_unregister_card;
1209 }
1210
1211 return 0;
1212
1213err_unregister_card:
1214 snd_soc_unregister_card(card);
1215err_switch_unregister:
1216#ifdef CONFIG_SWITCH
1217 switch_dev_unregister(&aic326x_wired_switch_dev);
1218#endif
1219err_fini_utils:
1220 tegra_asoc_utils_fini(&machine->util_data);
1221err_free_machine:
1222 kfree(machine);
1223 return ret;
1224}
1225
1226static int __devexit tegra_aic326x_driver_remove(struct platform_device *pdev)
1227{
1228 struct snd_soc_card *card = platform_get_drvdata(pdev);
1229 struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
1230 struct tegra_aic326x_platform_data *pdata = machine->pdata;
1231
1232 snd_soc_unregister_card(card);
1233
1234#ifdef CONFIG_SWITCH
1235 switch_dev_unregister(&aic326x_wired_switch_dev);
1236#endif
1237
1238 tegra_asoc_utils_fini(&machine->util_data);
1239
1240 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
1241 gpio_free(pdata->gpio_ext_mic_en);
1242 if (machine->gpio_requested & GPIO_INT_MIC_EN)
1243 gpio_free(pdata->gpio_int_mic_en);
1244 if (machine->gpio_requested & GPIO_HP_MUTE)
1245 gpio_free(pdata->gpio_hp_mute);
1246 if (machine->gpio_requested & GPIO_SPKR_EN)
1247 gpio_free(pdata->gpio_spkr_en);
1248
1249 kfree(machine);
1250
1251 return 0;
1252}
1253
1254static struct platform_driver tegra_aic326x_driver = {
1255 .driver = {
1256 .name = DRV_NAME,
1257 .owner = THIS_MODULE,
1258 .pm = &snd_soc_pm_ops,
1259 },
1260 .probe = tegra_aic326x_driver_probe,
1261 .remove = __devexit_p(tegra_aic326x_driver_remove),
1262};
1263
1264static int __init tegra_aic326x_modinit(void)
1265{
1266 return platform_driver_register(&tegra_aic326x_driver);
1267}
1268module_init(tegra_aic326x_modinit);
1269
1270static void __exit tegra_aic326x_modexit(void)
1271{
1272 platform_driver_unregister(&tegra_aic326x_driver);
1273}
1274module_exit(tegra_aic326x_modexit);
1275
1276/* Module information */
1277MODULE_AUTHOR("Vinod G. <vinodg@nvidia.com>");
1278MODULE_DESCRIPTION("Tegra+AIC3262 machine ASoC driver");
1279MODULE_DESCRIPTION("Tegra ALSA SoC");
1280MODULE_LICENSE("GPL");
1281
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index dfa85cbb05c..04e7e3c15cd 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -25,21 +25,39 @@
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27 27
28#include <mach/clk.h>
29
28#include "tegra_asoc_utils.h" 30#include "tegra_asoc_utils.h"
29 31
32int g_is_call_mode;
33
34bool tegra_is_voice_call_active()
35{
36 if (g_is_call_mode)
37 return true;
38 else
39 return false;
40}
41EXPORT_SYMBOL_GPL(tegra_is_voice_call_active);
42
30int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, 43int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
31 int mclk) 44 int mclk)
32{ 45{
33 int new_baseclock; 46 int new_baseclock;
34 bool clk_change; 47 bool clk_change;
35 int err; 48 int err;
49 bool reenable_clock;
36 50
37 switch (srate) { 51 switch (srate) {
38 case 11025: 52 case 11025:
39 case 22050: 53 case 22050:
40 case 44100: 54 case 44100:
41 case 88200: 55 case 88200:
56#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
42 new_baseclock = 56448000; 57 new_baseclock = 56448000;
58#else
59 new_baseclock = 564480000;
60#endif
43 break; 61 break;
44 case 8000: 62 case 8000:
45 case 16000: 63 case 16000:
@@ -47,7 +65,11 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
47 case 48000: 65 case 48000:
48 case 64000: 66 case 64000:
49 case 96000: 67 case 96000:
68#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
50 new_baseclock = 73728000; 69 new_baseclock = 73728000;
70#else
71 new_baseclock = 552960000;
72#endif
51 break; 73 break;
52 default: 74 default:
53 return -EINVAL; 75 return -EINVAL;
@@ -58,38 +80,60 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
58 if (!clk_change) 80 if (!clk_change)
59 return 0; 81 return 0;
60 82
83 /* Don't change rate if already one dai-link is using it */
84 if (data->lock_count)
85 return -EINVAL;
86
61 data->set_baseclock = 0; 87 data->set_baseclock = 0;
62 data->set_mclk = 0; 88 data->set_mclk = 0;
63 89
64 clk_disable(data->clk_cdev1); 90 reenable_clock = false;
65 clk_disable(data->clk_pll_a_out0); 91 if(tegra_is_clk_enabled(data->clk_pll_a)) {
66 clk_disable(data->clk_pll_a); 92 clk_disable(data->clk_pll_a);
67 93 reenable_clock = true;
94 }
68 err = clk_set_rate(data->clk_pll_a, new_baseclock); 95 err = clk_set_rate(data->clk_pll_a, new_baseclock);
69 if (err) { 96 if (err) {
70 dev_err(data->dev, "Can't set pll_a rate: %d\n", err); 97 dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
71 return err; 98 return err;
72 } 99 }
100 if(reenable_clock)
101 clk_enable(data->clk_pll_a);
73 102
103 reenable_clock = false;
104 if(tegra_is_clk_enabled(data->clk_pll_a_out0)) {
105 clk_disable(data->clk_pll_a_out0);
106 reenable_clock = true;
107 }
74 err = clk_set_rate(data->clk_pll_a_out0, mclk); 108 err = clk_set_rate(data->clk_pll_a_out0, mclk);
75 if (err) { 109 if (err) {
76 dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); 110 dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", err);
77 return err; 111 return err;
78 } 112 }
113 if(reenable_clock)
114 clk_enable(data->clk_pll_a_out0);
79 115
80 /* Don't set cdev1 rate; its locked to pll_a_out0 */
81 116
82 err = clk_enable(data->clk_pll_a); 117 data->set_baseclock = new_baseclock;
83 if (err) { 118 data->set_mclk = mclk;
84 dev_err(data->dev, "Can't enable pll_a: %d\n", err);
85 return err;
86 }
87 119
88 err = clk_enable(data->clk_pll_a_out0); 120 return 0;
89 if (err) { 121}
90 dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); 122EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);
91 return err; 123
92 } 124void tegra_asoc_utils_lock_clk_rate(struct tegra_asoc_utils_data *data,
125 int lock)
126{
127 if (lock)
128 data->lock_count++;
129 else if (data->lock_count)
130 data->lock_count--;
131}
132EXPORT_SYMBOL_GPL(tegra_asoc_utils_lock_clk_rate);
133
134int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data)
135{
136 int err;
93 137
94 err = clk_enable(data->clk_cdev1); 138 err = clk_enable(data->clk_cdev1);
95 if (err) { 139 if (err) {
@@ -97,25 +141,37 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
97 return err; 141 return err;
98 } 142 }
99 143
100 data->set_baseclock = new_baseclock; 144 return 0;
101 data->set_mclk = mclk; 145}
146EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable);
102 147
148int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data)
149{
150 clk_disable(data->clk_cdev1);
103 return 0; 151 return 0;
104} 152}
105EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate); 153EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable);
106 154
107int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, 155int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
108 struct device *dev) 156 struct device *dev)
109{ 157{
110 int ret; 158 int ret;
159 int rate;
111 160
112 data->dev = dev; 161 data->dev = dev;
113 162
163 data->clk_pll_p_out1 = clk_get_sys(NULL, "pll_p_out1");
164 if (IS_ERR(data->clk_pll_p_out1)) {
165 dev_err(data->dev, "Can't retrieve clk pll_p_out1\n");
166 ret = PTR_ERR(data->clk_pll_p_out1);
167 goto err;
168 }
169
114 data->clk_pll_a = clk_get_sys(NULL, "pll_a"); 170 data->clk_pll_a = clk_get_sys(NULL, "pll_a");
115 if (IS_ERR(data->clk_pll_a)) { 171 if (IS_ERR(data->clk_pll_a)) {
116 dev_err(data->dev, "Can't retrieve clk pll_a\n"); 172 dev_err(data->dev, "Can't retrieve clk pll_a\n");
117 ret = PTR_ERR(data->clk_pll_a); 173 ret = PTR_ERR(data->clk_pll_a);
118 goto err; 174 goto err_put_pll_p_out1;
119 } 175 }
120 176
121 data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); 177 data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
@@ -125,19 +181,90 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
125 goto err_put_pll_a; 181 goto err_put_pll_a;
126 } 182 }
127 183
184 data->clk_m = clk_get_sys(NULL, "clk_m");
185 if (IS_ERR(data->clk_m)) {
186 dev_err(data->dev, "Can't retrieve clk clk_m\n");
187 ret = PTR_ERR(data->clk_m);
188 goto err;
189 }
190
191#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
128 data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); 192 data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
193#else
194 data->clk_cdev1 = clk_get_sys("extern1", NULL);
195#endif
129 if (IS_ERR(data->clk_cdev1)) { 196 if (IS_ERR(data->clk_cdev1)) {
130 dev_err(data->dev, "Can't retrieve clk cdev1\n"); 197 dev_err(data->dev, "Can't retrieve clk cdev1\n");
131 ret = PTR_ERR(data->clk_cdev1); 198 ret = PTR_ERR(data->clk_cdev1);
132 goto err_put_pll_a_out0; 199 goto err_put_pll_a_out0;
133 } 200 }
134 201
202#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
203 data->clk_out1 = ERR_PTR(-ENOENT);
204#else
205 data->clk_out1 = clk_get_sys("clk_out_1", "extern1");
206 if (IS_ERR(data->clk_out1)) {
207 dev_err(data->dev, "Can't retrieve clk out1\n");
208 ret = PTR_ERR(data->clk_out1);
209 goto err_put_cdev1;
210 }
211#endif
212
213#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
214#if TEGRA30_I2S_MASTER_PLAYBACK
215 ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
216 if (ret) {
217 dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
218 goto err_put_out1;
219 }
220#else
221 rate = clk_get_rate(data->clk_m);
222
223 if(rate == 26000000)
224 clk_set_rate(data->clk_cdev1, 13000000);
225
226 ret = clk_set_parent(data->clk_cdev1, data->clk_m);
227 if (ret) {
228 dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
229 goto err_put_out1;
230 }
231#endif
232
233#endif
234
235 ret = clk_enable(data->clk_cdev1);
236 if (ret) {
237 dev_err(data->dev, "Can't enable clk cdev1/extern1");
238 goto err_put_out1;
239 }
240
241 if (!IS_ERR(data->clk_out1)) {
242 ret = clk_enable(data->clk_out1);
243 if (ret) {
244 dev_err(data->dev, "Can't enable clk out1");
245 goto err_put_out1;
246 }
247 }
248
249 ret = tegra_asoc_utils_set_rate(data, 48000, 256 * 48000);
250 if (ret)
251 goto err_put_out1;
252
135 return 0; 253 return 0;
136 254
255err_put_out1:
256 if (!IS_ERR(data->clk_out1))
257 clk_put(data->clk_out1);
258#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
259err_put_cdev1:
260#endif
261 clk_put(data->clk_cdev1);
137err_put_pll_a_out0: 262err_put_pll_a_out0:
138 clk_put(data->clk_pll_a_out0); 263 clk_put(data->clk_pll_a_out0);
139err_put_pll_a: 264err_put_pll_a:
140 clk_put(data->clk_pll_a); 265 clk_put(data->clk_pll_a);
266err_put_pll_p_out1:
267 clk_put(data->clk_pll_p_out1);
141err: 268err:
142 return ret; 269 return ret;
143} 270}
@@ -145,9 +272,19 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
145 272
146void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) 273void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
147{ 274{
275 if (!IS_ERR(data->clk_out1))
276 clk_put(data->clk_out1);
277
148 clk_put(data->clk_cdev1); 278 clk_put(data->clk_cdev1);
149 clk_put(data->clk_pll_a_out0); 279
150 clk_put(data->clk_pll_a); 280 if (!IS_ERR(data->clk_pll_a_out0))
281 clk_put(data->clk_pll_a_out0);
282
283 if (!IS_ERR(data->clk_pll_a))
284 clk_put(data->clk_pll_a);
285
286 if (!IS_ERR(data->clk_pll_p_out1))
287 clk_put(data->clk_pll_p_out1);
151} 288}
152EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini); 289EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini);
153 290
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 4818195da25..1c4e521cb4b 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -23,6 +23,9 @@
23#ifndef __TEGRA_ASOC_UTILS_H__ 23#ifndef __TEGRA_ASOC_UTILS_H__
24#define __TEGRA_ASOC_UTILS_H_ 24#define __TEGRA_ASOC_UTILS_H_
25 25
26
27#define TEGRA30_I2S_MASTER_PLAYBACK 1
28
26struct clk; 29struct clk;
27struct device; 30struct device;
28 31
@@ -31,15 +34,23 @@ struct tegra_asoc_utils_data {
31 struct clk *clk_pll_a; 34 struct clk *clk_pll_a;
32 struct clk *clk_pll_a_out0; 35 struct clk *clk_pll_a_out0;
33 struct clk *clk_cdev1; 36 struct clk *clk_cdev1;
37 struct clk *clk_out1;
38 struct clk *clk_m;
39 struct clk *clk_pll_p_out1;
34 int set_baseclock; 40 int set_baseclock;
35 int set_mclk; 41 int set_mclk;
42 int lock_count;
36}; 43};
37 44
38int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, 45int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
39 int mclk); 46 int mclk);
47void tegra_asoc_utils_lock_clk_rate(struct tegra_asoc_utils_data *data,
48 int lock);
40int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, 49int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
41 struct device *dev); 50 struct device *dev);
42void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); 51void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data);
52int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data);
53int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data);
43 54
44#endif 55#endif
45 56
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
deleted file mode 100644
index 9f24ef73f2c..00000000000
--- a/sound/soc/tegra/tegra_das.c
+++ /dev/null
@@ -1,265 +0,0 @@
1/*
2 * tegra_das.c - Tegra DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, 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/debugfs.h>
25#include <linux/device.h>
26#include <linux/platform_device.h>
27#include <linux/seq_file.h>
28#include <linux/slab.h>
29#include <linux/io.h>
30#include <mach/iomap.h>
31#include <sound/soc.h>
32#include "tegra_das.h"
33
34#define DRV_NAME "tegra-das"
35
36static struct tegra_das *das;
37
38static inline void tegra_das_write(u32 reg, u32 val)
39{
40 __raw_writel(val, das->regs + reg);
41}
42
43static inline u32 tegra_das_read(u32 reg)
44{
45 return __raw_readl(das->regs + reg);
46}
47
48int tegra_das_connect_dap_to_dac(int dap, int dac)
49{
50 u32 addr;
51 u32 reg;
52
53 if (!das)
54 return -ENODEV;
55
56 addr = TEGRA_DAS_DAP_CTRL_SEL +
57 (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
58 reg = dac << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
59
60 tegra_das_write(addr, reg);
61
62 return 0;
63}
64EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac);
65
66int tegra_das_connect_dap_to_dap(int dap, int otherdap, int master,
67 int sdata1rx, int sdata2rx)
68{
69 u32 addr;
70 u32 reg;
71
72 if (!das)
73 return -ENODEV;
74
75 addr = TEGRA_DAS_DAP_CTRL_SEL +
76 (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
77 reg = otherdap << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
78 !!sdata2rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
79 !!sdata1rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
80 !!master << TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
81
82 tegra_das_write(addr, reg);
83
84 return 0;
85}
86EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap);
87
88int tegra_das_connect_dac_to_dap(int dac, int dap)
89{
90 u32 addr;
91 u32 reg;
92
93 if (!das)
94 return -ENODEV;
95
96 addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
97 (dac * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
98 reg = dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
99 dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
100 dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
101
102 tegra_das_write(addr, reg);
103
104 return 0;
105}
106EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap);
107
108#ifdef CONFIG_DEBUG_FS
109static int tegra_das_show(struct seq_file *s, void *unused)
110{
111 int i;
112 u32 addr;
113 u32 reg;
114
115 for (i = 0; i < TEGRA_DAS_DAP_CTRL_SEL_COUNT; i++) {
116 addr = TEGRA_DAS_DAP_CTRL_SEL +
117 (i * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
118 reg = tegra_das_read(addr);
119 seq_printf(s, "TEGRA_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg);
120 }
121
122 for (i = 0; i < TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) {
123 addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
124 (i * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
125 reg = tegra_das_read(addr);
126 seq_printf(s, "TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n",
127 i, reg);
128 }
129
130 return 0;
131}
132
133static int tegra_das_debug_open(struct inode *inode, struct file *file)
134{
135 return single_open(file, tegra_das_show, inode->i_private);
136}
137
138static const struct file_operations tegra_das_debug_fops = {
139 .open = tegra_das_debug_open,
140 .read = seq_read,
141 .llseek = seq_lseek,
142 .release = single_release,
143};
144
145static void tegra_das_debug_add(struct tegra_das *das)
146{
147 das->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
148 snd_soc_debugfs_root, das,
149 &tegra_das_debug_fops);
150}
151
152static void tegra_das_debug_remove(struct tegra_das *das)
153{
154 if (das->debug)
155 debugfs_remove(das->debug);
156}
157#else
158static inline void tegra_das_debug_add(struct tegra_das *das)
159{
160}
161
162static inline void tegra_das_debug_remove(struct tegra_das *das)
163{
164}
165#endif
166
167static int __devinit tegra_das_probe(struct platform_device *pdev)
168{
169 struct resource *res, *region;
170 int ret = 0;
171
172 if (das)
173 return -ENODEV;
174
175 das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
176 if (!das) {
177 dev_err(&pdev->dev, "Can't allocate tegra_das\n");
178 ret = -ENOMEM;
179 goto exit;
180 }
181 das->dev = &pdev->dev;
182
183 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
184 if (!res) {
185 dev_err(&pdev->dev, "No memory resource\n");
186 ret = -ENODEV;
187 goto err_free;
188 }
189
190 region = request_mem_region(res->start, resource_size(res),
191 pdev->name);
192 if (!region) {
193 dev_err(&pdev->dev, "Memory region already claimed\n");
194 ret = -EBUSY;
195 goto err_free;
196 }
197
198 das->regs = ioremap(res->start, resource_size(res));
199 if (!das->regs) {
200 dev_err(&pdev->dev, "ioremap failed\n");
201 ret = -ENOMEM;
202 goto err_release;
203 }
204
205 tegra_das_debug_add(das);
206
207 platform_set_drvdata(pdev, das);
208
209 return 0;
210
211err_release:
212 release_mem_region(res->start, resource_size(res));
213err_free:
214 kfree(das);
215 das = 0;
216exit:
217 return ret;
218}
219
220static int __devexit tegra_das_remove(struct platform_device *pdev)
221{
222 struct resource *res;
223
224 if (!das)
225 return -ENODEV;
226
227 platform_set_drvdata(pdev, NULL);
228
229 tegra_das_debug_remove(das);
230
231 iounmap(das->regs);
232
233 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
234 release_mem_region(res->start, resource_size(res));
235
236 kfree(das);
237 das = 0;
238
239 return 0;
240}
241
242static struct platform_driver tegra_das_driver = {
243 .probe = tegra_das_probe,
244 .remove = __devexit_p(tegra_das_remove),
245 .driver = {
246 .name = DRV_NAME,
247 },
248};
249
250static int __init tegra_das_modinit(void)
251{
252 return platform_driver_register(&tegra_das_driver);
253}
254module_init(tegra_das_modinit);
255
256static void __exit tegra_das_modexit(void)
257{
258 platform_driver_unregister(&tegra_das_driver);
259}
260module_exit(tegra_das_modexit);
261
262MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
263MODULE_DESCRIPTION("Tegra DAS driver");
264MODULE_LICENSE("GPL");
265MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_das.h b/sound/soc/tegra/tegra_das.h
deleted file mode 100644
index 2c96c7b3c45..00000000000
--- a/sound/soc/tegra/tegra_das.h
+++ /dev/null
@@ -1,135 +0,0 @@
1/*
2 * tegra_das.h - Definitions for Tegra DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, 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#ifndef __TEGRA_DAS_H__
24#define __TEGRA_DAS_H__
25
26/* Register TEGRA_DAS_DAP_CTRL_SEL */
27#define TEGRA_DAS_DAP_CTRL_SEL 0x00
28#define TEGRA_DAS_DAP_CTRL_SEL_COUNT 5
29#define TEGRA_DAS_DAP_CTRL_SEL_STRIDE 4
30#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31
31#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1
32#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30
33#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1
34#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29
35#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1
36#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0
37#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5
38
39/* Values for field TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
40#define TEGRA_DAS_DAP_SEL_DAC1 0
41#define TEGRA_DAS_DAP_SEL_DAC2 1
42#define TEGRA_DAS_DAP_SEL_DAC3 2
43#define TEGRA_DAS_DAP_SEL_DAP1 16
44#define TEGRA_DAS_DAP_SEL_DAP2 17
45#define TEGRA_DAS_DAP_SEL_DAP3 18
46#define TEGRA_DAS_DAP_SEL_DAP4 19
47#define TEGRA_DAS_DAP_SEL_DAP5 20
48
49/* Register TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL */
50#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL 0x40
51#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3
52#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4
53#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28
54#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4
55#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24
56#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4
57#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0
58#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4
59
60/*
61 * Values for:
62 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
63 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
64 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
65 */
66#define TEGRA_DAS_DAC_SEL_DAP1 0
67#define TEGRA_DAS_DAC_SEL_DAP2 1
68#define TEGRA_DAS_DAC_SEL_DAP3 2
69#define TEGRA_DAS_DAC_SEL_DAP4 3
70#define TEGRA_DAS_DAC_SEL_DAP5 4
71
72/*
73 * Names/IDs of the DACs/DAPs.
74 */
75
76#define TEGRA_DAS_DAP_ID_1 0
77#define TEGRA_DAS_DAP_ID_2 1
78#define TEGRA_DAS_DAP_ID_3 2
79#define TEGRA_DAS_DAP_ID_4 3
80#define TEGRA_DAS_DAP_ID_5 4
81
82#define TEGRA_DAS_DAC_ID_1 0
83#define TEGRA_DAS_DAC_ID_2 1
84#define TEGRA_DAS_DAC_ID_3 2
85
86struct tegra_das {
87 struct device *dev;
88 void __iomem *regs;
89 struct dentry *debug;
90};
91
92/*
93 * Terminology:
94 * DAS: Digital audio switch (HW module controlled by this driver)
95 * DAP: Digital audio port (port/pins on Tegra device)
96 * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
97 *
98 * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
99 * DAC, or another DAP. When DAPs are connected, one must be the master and
100 * one the slave. Each DAC allows selection of a specific DAP for input, to
101 * cater for the case where N DAPs are connected to 1 DAC for broadcast
102 * output.
103 *
104 * This driver is dumb; no attempt is made to ensure that a valid routing
105 * configuration is programmed.
106 */
107
108/*
109 * Connect a DAP to to a DAC
110 * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
111 * dac_sel: DAC to connect to: TEGRA_DAS_DAP_SEL_DAC*
112 */
113extern int tegra_das_connect_dap_to_dac(int dap_id, int dac_sel);
114
115/*
116 * Connect a DAP to to another DAP
117 * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
118 * other_dap_sel: DAP to connect to: TEGRA_DAS_DAP_SEL_DAP*
119 * master: Is this DAP the master (1) or slave (0)
120 * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
121 * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
122 */
123extern int tegra_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
124 int master, int sdata1rx,
125 int sdata2rx);
126
127/*
128 * Connect a DAC's input to a DAP
129 * (DAC outputs are selected by the DAP)
130 * dac_id: DAC ID to connect: TEGRA_DAS_DAC_ID_*
131 * dap_sel: DAP to receive input from: TEGRA_DAS_DAC_SEL_DAP*
132 */
133extern int tegra_das_connect_dac_to_dap(int dac_id, int dap_sel);
134
135#endif
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
deleted file mode 100644
index 95f03c10b4f..00000000000
--- a/sound/soc/tegra/tegra_i2s.c
+++ /dev/null
@@ -1,509 +0,0 @@
1/*
2 * tegra_i2s.c - Tegra I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <linux/clk.h>
32#include <linux/module.h>
33#include <linux/debugfs.h>
34#include <linux/device.h>
35#include <linux/platform_device.h>
36#include <linux/seq_file.h>
37#include <linux/slab.h>
38#include <linux/io.h>
39#include <mach/iomap.h>
40#include <sound/core.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "tegra_das.h"
46#include "tegra_i2s.h"
47
48#define DRV_NAME "tegra-i2s"
49
50static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val)
51{
52 __raw_writel(val, i2s->regs + reg);
53}
54
55static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg)
56{
57 return __raw_readl(i2s->regs + reg);
58}
59
60#ifdef CONFIG_DEBUG_FS
61static int tegra_i2s_show(struct seq_file *s, void *unused)
62{
63#define REG(r) { r, #r }
64 static const struct {
65 int offset;
66 const char *name;
67 } regs[] = {
68 REG(TEGRA_I2S_CTRL),
69 REG(TEGRA_I2S_STATUS),
70 REG(TEGRA_I2S_TIMING),
71 REG(TEGRA_I2S_FIFO_SCR),
72 REG(TEGRA_I2S_PCM_CTRL),
73 REG(TEGRA_I2S_NW_CTRL),
74 REG(TEGRA_I2S_TDM_CTRL),
75 REG(TEGRA_I2S_TDM_TX_RX_CTRL),
76 };
77#undef REG
78
79 struct tegra_i2s *i2s = s->private;
80 int i;
81
82 for (i = 0; i < ARRAY_SIZE(regs); i++) {
83 u32 val = tegra_i2s_read(i2s, regs[i].offset);
84 seq_printf(s, "%s = %08x\n", regs[i].name, val);
85 }
86
87 return 0;
88}
89
90static int tegra_i2s_debug_open(struct inode *inode, struct file *file)
91{
92 return single_open(file, tegra_i2s_show, inode->i_private);
93}
94
95static const struct file_operations tegra_i2s_debug_fops = {
96 .open = tegra_i2s_debug_open,
97 .read = seq_read,
98 .llseek = seq_lseek,
99 .release = single_release,
100};
101
102static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
103{
104 char name[] = DRV_NAME ".0";
105
106 snprintf(name, sizeof(name), DRV_NAME".%1d", id);
107 i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
108 i2s, &tegra_i2s_debug_fops);
109}
110
111static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
112{
113 if (i2s->debug)
114 debugfs_remove(i2s->debug);
115}
116#else
117static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
118{
119}
120
121static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
122{
123}
124#endif
125
126static int tegra_i2s_set_fmt(struct snd_soc_dai *dai,
127 unsigned int fmt)
128{
129 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
130
131 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
132 case SND_SOC_DAIFMT_NB_NF:
133 break;
134 default:
135 return -EINVAL;
136 }
137
138 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE;
139 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
140 case SND_SOC_DAIFMT_CBS_CFS:
141 i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE;
142 break;
143 case SND_SOC_DAIFMT_CBM_CFM:
144 break;
145 default:
146 return -EINVAL;
147 }
148
149 i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK |
150 TEGRA_I2S_CTRL_LRCK_MASK);
151 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
152 case SND_SOC_DAIFMT_DSP_A:
153 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
154 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
155 break;
156 case SND_SOC_DAIFMT_DSP_B:
157 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
158 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW;
159 break;
160 case SND_SOC_DAIFMT_I2S:
161 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S;
162 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
163 break;
164 case SND_SOC_DAIFMT_RIGHT_J:
165 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM;
166 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
167 break;
168 case SND_SOC_DAIFMT_LEFT_J:
169 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM;
170 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
171 break;
172 default:
173 return -EINVAL;
174 }
175
176 return 0;
177}
178
179static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
180 struct snd_pcm_hw_params *params,
181 struct snd_soc_dai *dai)
182{
183 struct device *dev = substream->pcm->card->dev;
184 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
185 u32 reg;
186 int ret, sample_size, srate, i2sclock, bitcnt;
187
188 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK;
189 switch (params_format(params)) {
190 case SNDRV_PCM_FORMAT_S16_LE:
191 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16;
192 sample_size = 16;
193 break;
194 case SNDRV_PCM_FORMAT_S24_LE:
195 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24;
196 sample_size = 24;
197 break;
198 case SNDRV_PCM_FORMAT_S32_LE:
199 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32;
200 sample_size = 32;
201 break;
202 default:
203 return -EINVAL;
204 }
205
206 srate = params_rate(params);
207
208 /* Final "* 2" required by Tegra hardware */
209 i2sclock = srate * params_channels(params) * sample_size * 2;
210
211 ret = clk_set_rate(i2s->clk_i2s, i2sclock);
212 if (ret) {
213 dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
214 return ret;
215 }
216
217 bitcnt = (i2sclock / (2 * srate)) - 1;
218 if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
219 return -EINVAL;
220 reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
221
222 if (i2sclock % (2 * srate))
223 reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE;
224
225 if (!i2s->clk_refs)
226 clk_enable(i2s->clk_i2s);
227
228 tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg);
229
230 tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR,
231 TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
232 TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
233
234 if (!i2s->clk_refs)
235 clk_disable(i2s->clk_i2s);
236
237 return 0;
238}
239
240static void tegra_i2s_start_playback(struct tegra_i2s *i2s)
241{
242 i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE;
243 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
244}
245
246static void tegra_i2s_stop_playback(struct tegra_i2s *i2s)
247{
248 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE;
249 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
250}
251
252static void tegra_i2s_start_capture(struct tegra_i2s *i2s)
253{
254 i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE;
255 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
256}
257
258static void tegra_i2s_stop_capture(struct tegra_i2s *i2s)
259{
260 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE;
261 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
262}
263
264static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
265 struct snd_soc_dai *dai)
266{
267 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
268
269 switch (cmd) {
270 case SNDRV_PCM_TRIGGER_START:
271 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
272 case SNDRV_PCM_TRIGGER_RESUME:
273 if (!i2s->clk_refs)
274 clk_enable(i2s->clk_i2s);
275 i2s->clk_refs++;
276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
277 tegra_i2s_start_playback(i2s);
278 else
279 tegra_i2s_start_capture(i2s);
280 break;
281 case SNDRV_PCM_TRIGGER_STOP:
282 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
283 case SNDRV_PCM_TRIGGER_SUSPEND:
284 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
285 tegra_i2s_stop_playback(i2s);
286 else
287 tegra_i2s_stop_capture(i2s);
288 i2s->clk_refs--;
289 if (!i2s->clk_refs)
290 clk_disable(i2s->clk_i2s);
291 break;
292 default:
293 return -EINVAL;
294 }
295
296 return 0;
297}
298
299static int tegra_i2s_probe(struct snd_soc_dai *dai)
300{
301 struct tegra_i2s * i2s = snd_soc_dai_get_drvdata(dai);
302
303 dai->capture_dma_data = &i2s->capture_dma_data;
304 dai->playback_dma_data = &i2s->playback_dma_data;
305
306 return 0;
307}
308
309static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
310 .set_fmt = tegra_i2s_set_fmt,
311 .hw_params = tegra_i2s_hw_params,
312 .trigger = tegra_i2s_trigger,
313};
314
315struct snd_soc_dai_driver tegra_i2s_dai[] = {
316 {
317 .name = DRV_NAME ".0",
318 .probe = tegra_i2s_probe,
319 .playback = {
320 .channels_min = 2,
321 .channels_max = 2,
322 .rates = SNDRV_PCM_RATE_8000_96000,
323 .formats = SNDRV_PCM_FMTBIT_S16_LE,
324 },
325 .capture = {
326 .channels_min = 2,
327 .channels_max = 2,
328 .rates = SNDRV_PCM_RATE_8000_96000,
329 .formats = SNDRV_PCM_FMTBIT_S16_LE,
330 },
331 .ops = &tegra_i2s_dai_ops,
332 .symmetric_rates = 1,
333 },
334 {
335 .name = DRV_NAME ".1",
336 .probe = tegra_i2s_probe,
337 .playback = {
338 .channels_min = 2,
339 .channels_max = 2,
340 .rates = SNDRV_PCM_RATE_8000_96000,
341 .formats = SNDRV_PCM_FMTBIT_S16_LE,
342 },
343 .capture = {
344 .channels_min = 2,
345 .channels_max = 2,
346 .rates = SNDRV_PCM_RATE_8000_96000,
347 .formats = SNDRV_PCM_FMTBIT_S16_LE,
348 },
349 .ops = &tegra_i2s_dai_ops,
350 .symmetric_rates = 1,
351 },
352};
353
354static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
355{
356 struct tegra_i2s * i2s;
357 char clk_name[12]; /* tegra-i2s.0 */
358 struct resource *mem, *memregion, *dmareq;
359 int ret;
360
361 if ((pdev->id < 0) ||
362 (pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
363 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
364 return -EINVAL;
365 }
366
367 /*
368 * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
369 * 1:1 mapping between audio controllers and audio ports.
370 */
371 ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
372 TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
373 if (ret) {
374 dev_err(&pdev->dev, "Can't set up DAP connection\n");
375 return ret;
376 }
377 ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
378 TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
379 if (ret) {
380 dev_err(&pdev->dev, "Can't set up DAC connection\n");
381 return ret;
382 }
383
384 i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
385 if (!i2s) {
386 dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
387 ret = -ENOMEM;
388 goto exit;
389 }
390 dev_set_drvdata(&pdev->dev, i2s);
391
392 snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id);
393 i2s->clk_i2s = clk_get_sys(clk_name, NULL);
394 if (IS_ERR(i2s->clk_i2s)) {
395 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
396 ret = PTR_ERR(i2s->clk_i2s);
397 goto err_free;
398 }
399
400 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
401 if (!mem) {
402 dev_err(&pdev->dev, "No memory resource\n");
403 ret = -ENODEV;
404 goto err_clk_put;
405 }
406
407 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
408 if (!dmareq) {
409 dev_err(&pdev->dev, "No DMA resource\n");
410 ret = -ENODEV;
411 goto err_clk_put;
412 }
413
414 memregion = request_mem_region(mem->start, resource_size(mem),
415 DRV_NAME);
416 if (!memregion) {
417 dev_err(&pdev->dev, "Memory region already claimed\n");
418 ret = -EBUSY;
419 goto err_clk_put;
420 }
421
422 i2s->regs = ioremap(mem->start, resource_size(mem));
423 if (!i2s->regs) {
424 dev_err(&pdev->dev, "ioremap failed\n");
425 ret = -ENOMEM;
426 goto err_release;
427 }
428
429 i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
430 i2s->capture_dma_data.wrap = 4;
431 i2s->capture_dma_data.width = 32;
432 i2s->capture_dma_data.req_sel = dmareq->start;
433
434 i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
435 i2s->playback_dma_data.wrap = 4;
436 i2s->playback_dma_data.width = 32;
437 i2s->playback_dma_data.req_sel = dmareq->start;
438
439 i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
440
441 ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
442 if (ret) {
443 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
444 ret = -ENOMEM;
445 goto err_unmap;
446 }
447
448 tegra_i2s_debug_add(i2s, pdev->id);
449
450 return 0;
451
452err_unmap:
453 iounmap(i2s->regs);
454err_release:
455 release_mem_region(mem->start, resource_size(mem));
456err_clk_put:
457 clk_put(i2s->clk_i2s);
458err_free:
459 kfree(i2s);
460exit:
461 return ret;
462}
463
464static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
465{
466 struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
467 struct resource *res;
468
469 snd_soc_unregister_dai(&pdev->dev);
470
471 tegra_i2s_debug_remove(i2s);
472
473 iounmap(i2s->regs);
474
475 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
476 release_mem_region(res->start, resource_size(res));
477
478 clk_put(i2s->clk_i2s);
479
480 kfree(i2s);
481
482 return 0;
483}
484
485static struct platform_driver tegra_i2s_driver = {
486 .driver = {
487 .name = DRV_NAME,
488 .owner = THIS_MODULE,
489 },
490 .probe = tegra_i2s_platform_probe,
491 .remove = __devexit_p(tegra_i2s_platform_remove),
492};
493
494static int __init snd_tegra_i2s_init(void)
495{
496 return platform_driver_register(&tegra_i2s_driver);
497}
498module_init(snd_tegra_i2s_init);
499
500static void __exit snd_tegra_i2s_exit(void)
501{
502 platform_driver_unregister(&tegra_i2s_driver);
503}
504module_exit(snd_tegra_i2s_exit);
505
506MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
507MODULE_DESCRIPTION("Tegra I2S ASoC driver");
508MODULE_LICENSE("GPL");
509MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
deleted file mode 100644
index 2b38a096f46..00000000000
--- a/sound/soc/tegra/tegra_i2s.h
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * tegra_i2s.h - Definitions for Tegra I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#ifndef __TEGRA_I2S_H__
32#define __TEGRA_I2S_H__
33
34#include "tegra_pcm.h"
35
36/* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */
37
38#define TEGRA_I2S_CTRL 0x00
39#define TEGRA_I2S_STATUS 0x04
40#define TEGRA_I2S_TIMING 0x08
41#define TEGRA_I2S_FIFO_SCR 0x0c
42#define TEGRA_I2S_PCM_CTRL 0x10
43#define TEGRA_I2S_NW_CTRL 0x14
44#define TEGRA_I2S_TDM_CTRL 0x20
45#define TEGRA_I2S_TDM_TX_RX_CTRL 0x24
46#define TEGRA_I2S_FIFO1 0x40
47#define TEGRA_I2S_FIFO2 0x80
48
49/* Fields in TEGRA_I2S_CTRL */
50
51#define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30)
52#define TEGRA_I2S_CTRL_FIFO1_ENABLE (1 << 29)
53#define TEGRA_I2S_CTRL_FIFO2_ENABLE (1 << 28)
54#define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27)
55#define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26)
56#define TEGRA_I2S_CTRL_MASTER_ENABLE (1 << 25)
57
58#define TEGRA_I2S_LRCK_LEFT_LOW 0
59#define TEGRA_I2S_LRCK_RIGHT_LOW 1
60
61#define TEGRA_I2S_CTRL_LRCK_SHIFT 24
62#define TEGRA_I2S_CTRL_LRCK_MASK (1 << TEGRA_I2S_CTRL_LRCK_SHIFT)
63#define TEGRA_I2S_CTRL_LRCK_L_LOW (TEGRA_I2S_LRCK_LEFT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
64#define TEGRA_I2S_CTRL_LRCK_R_LOW (TEGRA_I2S_LRCK_RIGHT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
65
66#define TEGRA_I2S_BIT_FORMAT_I2S 0
67#define TEGRA_I2S_BIT_FORMAT_RJM 1
68#define TEGRA_I2S_BIT_FORMAT_LJM 2
69#define TEGRA_I2S_BIT_FORMAT_DSP 3
70
71#define TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT 10
72#define TEGRA_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
73#define TEGRA_I2S_CTRL_BIT_FORMAT_I2S (TEGRA_I2S_BIT_FORMAT_I2S << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
74#define TEGRA_I2S_CTRL_BIT_FORMAT_RJM (TEGRA_I2S_BIT_FORMAT_RJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
75#define TEGRA_I2S_CTRL_BIT_FORMAT_LJM (TEGRA_I2S_BIT_FORMAT_LJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
76#define TEGRA_I2S_CTRL_BIT_FORMAT_DSP (TEGRA_I2S_BIT_FORMAT_DSP << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
77
78#define TEGRA_I2S_BIT_SIZE_16 0
79#define TEGRA_I2S_BIT_SIZE_20 1
80#define TEGRA_I2S_BIT_SIZE_24 2
81#define TEGRA_I2S_BIT_SIZE_32 3
82
83#define TEGRA_I2S_CTRL_BIT_SIZE_SHIFT 8
84#define TEGRA_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
85#define TEGRA_I2S_CTRL_BIT_SIZE_16 (TEGRA_I2S_BIT_SIZE_16 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
86#define TEGRA_I2S_CTRL_BIT_SIZE_20 (TEGRA_I2S_BIT_SIZE_20 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
87#define TEGRA_I2S_CTRL_BIT_SIZE_24 (TEGRA_I2S_BIT_SIZE_24 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
88#define TEGRA_I2S_CTRL_BIT_SIZE_32 (TEGRA_I2S_BIT_SIZE_32 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
89
90#define TEGRA_I2S_FIFO_16_LSB 0
91#define TEGRA_I2S_FIFO_20_LSB 1
92#define TEGRA_I2S_FIFO_24_LSB 2
93#define TEGRA_I2S_FIFO_32 3
94#define TEGRA_I2S_FIFO_PACKED 7
95
96#define TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT 4
97#define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
98#define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA_I2S_FIFO_16_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
99#define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA_I2S_FIFO_20_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
100#define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA_I2S_FIFO_24_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
101#define TEGRA_I2S_CTRL_FIFO_FORMAT_32 (TEGRA_I2S_FIFO_32 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
102#define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA_I2S_FIFO_PACKED << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
103
104#define TEGRA_I2S_CTRL_IE_FIFO1_ERR (1 << 3)
105#define TEGRA_I2S_CTRL_IE_FIFO2_ERR (1 << 2)
106#define TEGRA_I2S_CTRL_QE_FIFO1 (1 << 1)
107#define TEGRA_I2S_CTRL_QE_FIFO2 (1 << 0)
108
109/* Fields in TEGRA_I2S_STATUS */
110
111#define TEGRA_I2S_STATUS_FIFO1_RDY (1 << 31)
112#define TEGRA_I2S_STATUS_FIFO2_RDY (1 << 30)
113#define TEGRA_I2S_STATUS_FIFO1_BSY (1 << 29)
114#define TEGRA_I2S_STATUS_FIFO2_BSY (1 << 28)
115#define TEGRA_I2S_STATUS_FIFO1_ERR (1 << 3)
116#define TEGRA_I2S_STATUS_FIFO2_ERR (1 << 2)
117#define TEGRA_I2S_STATUS_QS_FIFO1 (1 << 1)
118#define TEGRA_I2S_STATUS_QS_FIFO2 (1 << 0)
119
120/* Fields in TEGRA_I2S_TIMING */
121
122#define TEGRA_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
123#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
124#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
125#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
126
127/* Fields in TEGRA_I2S_FIFO_SCR */
128
129#define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24
130#define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16
131#define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f
132
133#define TEGRA_I2S_FIFO_SCR_FIFO2_CLR (1 << 12)
134#define TEGRA_I2S_FIFO_SCR_FIFO1_CLR (1 << 8)
135
136#define TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT 0
137#define TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1
138#define TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2
139#define TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3
140
141#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4
142#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
143#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
144#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
145#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
146#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
147
148#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0
149#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
150#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
151#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
152#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
153#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
154
155struct tegra_i2s {
156 struct clk *clk_i2s;
157 int clk_refs;
158 struct tegra_pcm_dma_params capture_dma_data;
159 struct tegra_pcm_dma_params playback_dma_data;
160 void __iomem *regs;
161 struct dentry *debug;
162 u32 reg_ctrl;
163};
164
165#endif
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c
new file mode 100644
index 00000000000..bae2b783895
--- /dev/null
+++ b/sound/soc/tegra/tegra_max98088.c
@@ -0,0 +1,1233 @@
1/*
2 * tegra_max98088.c - Tegra machine ASoC driver for boards using MAX98088 codec.
3 *
4 * Author: Sumit Bhattacharya <sumitb@nvidia.com>
5 * Copyright (C) 2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2010, 2011 Nvidia Graphics Pvt. Ltd.
10 *
11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <asm/mach-types.h>
32
33#include <linux/clk.h>
34#include <linux/module.h>
35#include <linux/platform_device.h>
36#include <linux/slab.h>
37#include <linux/gpio.h>
38#include <linux/regulator/consumer.h>
39#ifdef CONFIG_SWITCH
40#include <linux/switch.h>
41#endif
42
43#include <mach/tegra_asoc_pdata.h>
44
45#include <sound/core.h>
46#include <sound/jack.h>
47#include <sound/pcm.h>
48#include <sound/pcm_params.h>
49#include <sound/soc.h>
50
51#include "../codecs/max98088.h"
52
53#include "tegra_pcm.h"
54#include "tegra_asoc_utils.h"
55#ifndef CONFIG_ARCH_TEGRA_2x_SOC
56#include "tegra30_ahub.h"
57#include "tegra30_i2s.h"
58#include "tegra30_dam.h"
59#endif
60
61#define DRV_NAME "tegra-snd-max98088"
62
63#define GPIO_SPKR_EN BIT(0)
64#define GPIO_HP_MUTE BIT(1)
65#define GPIO_INT_MIC_EN BIT(2)
66#define GPIO_EXT_MIC_EN BIT(3)
67
68#define DAI_LINK_HIFI 0
69#define DAI_LINK_SPDIF 1
70#define DAI_LINK_BTSCO 2
71#define DAI_LINK_VOICE_CALL 3
72#define DAI_LINK_BT_VOICE_CALL 4
73#define NUM_DAI_LINKS 5
74
75#ifndef CONFIG_ARCH_TEGRA_2x_SOC
76const char *tegra_max98088_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
77 "tegra30-i2s.0",
78 "tegra30-i2s.1",
79 "tegra30-i2s.2",
80 "tegra30-i2s.3",
81 "tegra30-i2s.4",
82};
83#endif
84
85extern int g_is_call_mode;
86
87struct tegra_max98088 {
88 struct tegra_asoc_utils_data util_data;
89 struct tegra_asoc_platform_data *pdata;
90 int gpio_requested;
91 bool init_done;
92 int is_call_mode;
93 int is_device_bt;
94#ifndef CONFIG_ARCH_TEGRA_2x_SOC
95 struct codec_config codec_info[NUM_I2S_DEVICES];
96#endif
97 enum snd_soc_bias_level bias_level;
98 struct snd_soc_card *pcard;
99};
100
101static int tegra_call_mode_info(struct snd_kcontrol *kcontrol,
102 struct snd_ctl_elem_info *uinfo)
103{
104 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
105 uinfo->count = 1;
106 uinfo->value.integer.min = 0;
107 uinfo->value.integer.max = 1;
108 return 0;
109}
110
111static int tegra_call_mode_get(struct snd_kcontrol *kcontrol,
112 struct snd_ctl_elem_value *ucontrol)
113{
114 struct tegra_max98088 *machine = snd_kcontrol_chip(kcontrol);
115
116 ucontrol->value.integer.value[0] = machine->is_call_mode;
117
118 return 0;
119}
120
121static int tegra_call_mode_put(struct snd_kcontrol *kcontrol,
122 struct snd_ctl_elem_value *ucontrol)
123{
124 struct tegra_max98088 *machine = snd_kcontrol_chip(kcontrol);
125 int is_call_mode_new = ucontrol->value.integer.value[0];
126 int codec_index;
127 unsigned int i;
128
129 if (machine->is_call_mode == is_call_mode_new)
130 return 0;
131
132 if (machine->is_device_bt)
133 codec_index = BT_SCO;
134 else
135 codec_index = HIFI_CODEC;
136
137 if (is_call_mode_new) {
138#ifndef CONFIG_ARCH_TEGRA_2x_SOC
139 if (machine->codec_info[codec_index].rate == 0 ||
140 machine->codec_info[codec_index].channels == 0)
141 return -EINVAL;
142
143 for (i = 0; i < machine->pcard->num_links; i++)
144 machine->pcard->dai_link[i].ignore_suspend = 1;
145
146 tegra30_make_voice_call_connections(
147 &machine->codec_info[codec_index],
148 &machine->codec_info[BASEBAND]);
149#endif
150 } else {
151#ifndef CONFIG_ARCH_TEGRA_2x_SOC
152 tegra30_break_voice_call_connections(
153 &machine->codec_info[codec_index],
154 &machine->codec_info[BASEBAND]);
155
156 for (i = 0; i < machine->pcard->num_links; i++)
157 machine->pcard->dai_link[i].ignore_suspend = 0;
158#endif
159 }
160
161 machine->is_call_mode = is_call_mode_new;
162 g_is_call_mode = machine->is_call_mode;
163
164 return 1;
165}
166
167struct snd_kcontrol_new tegra_call_mode_control = {
168 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
169 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
170 .name = "Call Mode Switch",
171 .private_value = 0xffff,
172 .info = tegra_call_mode_info,
173 .get = tegra_call_mode_get,
174 .put = tegra_call_mode_put
175};
176
177#ifndef CONFIG_ARCH_TEGRA_2x_SOC
178static int tegra_max98088_set_dam_cif(int dam_ifc, int srate,
179 int channels, int bit_size, int src_on, int src_srate,
180 int src_channels, int src_bit_size)
181{
182 tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
183 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHOUT,
184 srate);
185 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN1,
186 srate);
187 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN1,
188 channels, bit_size, channels,
189 bit_size);
190 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHOUT,
191 channels, bit_size, channels,
192 bit_size);
193
194 if (src_on) {
195 tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN0_SRC, 0x1000);
196 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
197 src_srate);
198 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
199 src_channels, src_bit_size, 1, 16);
200 }
201
202 return 0;
203}
204#endif
205
206static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
207 struct snd_pcm_hw_params *params)
208{
209 struct snd_soc_pcm_runtime *rtd = substream->private_data;
210 struct snd_soc_dai *codec_dai = rtd->codec_dai;
211 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
212 struct snd_soc_codec *codec = rtd->codec;
213 struct snd_soc_card *card = codec->card;
214 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
215#ifndef CONFIG_ARCH_TEGRA_2x_SOC
216 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
217#endif
218 int srate, mclk, sample_size, i2s_daifmt;
219 int err;
220 struct clk *clk;
221 int rate;
222
223 switch (params_format(params)) {
224 case SNDRV_PCM_FORMAT_S16_LE:
225 sample_size = 16;
226 break;
227 default:
228 return -EINVAL;
229 }
230
231 srate = params_rate(params);
232 switch (srate) {
233 case 8000:
234 case 16000:
235 case 24000:
236 case 32000:
237 case 48000:
238 case 64000:
239 case 96000:
240 mclk = 12288000;
241 break;
242 case 11025:
243 case 22050:
244 case 44100:
245 case 88200:
246 mclk = 11289600;
247 break;
248 default:
249 mclk = 12000000;
250 break;
251 }
252
253
254#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
255 clk = clk_get_sys(NULL, "cdev1");
256#else
257 clk = clk_get_sys("extern1", NULL);
258#endif
259 if (IS_ERR(clk)) {
260 dev_err(card->dev, "Can't retrieve clk cdev1\n");
261 err = PTR_ERR(clk);
262 return err;
263 }
264
265 rate = clk_get_rate(clk);
266 printk("extern1 rate=%d\n",rate);
267
268#if TEGRA30_I2S_MASTER_PLAYBACK
269 i2s_daifmt = SND_SOC_DAIFMT_I2S |
270 SND_SOC_DAIFMT_NB_NF |
271 SND_SOC_DAIFMT_CBS_CFS;
272#else
273 i2s_daifmt = SND_SOC_DAIFMT_I2S |
274 SND_SOC_DAIFMT_NB_NF |
275 SND_SOC_DAIFMT_CBM_CFM;
276 mclk = rate;
277#endif
278
279 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
280 if (err < 0) {
281 if (!(machine->util_data.set_mclk % mclk))
282 mclk = machine->util_data.set_mclk;
283 else {
284 dev_err(card->dev, "Can't configure clocks\n");
285 return err;
286 }
287 }
288
289 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
290
291 err = snd_soc_dai_set_fmt(codec_dai,i2s_daifmt);
292 if (err < 0) {
293 dev_err(card->dev, "codec_dai fmt not set\n");
294 return err;
295 }
296
297 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
298 if (err < 0) {
299 dev_err(card->dev, "cpu_dai fmt not set\n");
300 return err;
301 }
302
303 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
304 SND_SOC_CLOCK_IN);
305 if (err < 0) {
306 dev_err(card->dev, "codec_dai clock not set\n");
307 return err;
308 }
309
310#ifndef CONFIG_ARCH_TEGRA_2x_SOC
311 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
312 tegra_max98088_set_dam_cif(i2s->dam_ifc, srate,
313 params_channels(params), sample_size, 0, 0, 0, 0);
314#endif
315
316 return 0;
317}
318
319static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
320 struct snd_pcm_hw_params *params)
321{
322 struct snd_soc_pcm_runtime *rtd = substream->private_data;
323 struct snd_soc_card *card = rtd->card;
324 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
325 int srate, mclk, min_mclk;
326 int err;
327
328 srate = params_rate(params);
329 switch (srate) {
330 case 11025:
331 case 22050:
332 case 44100:
333 case 88200:
334 mclk = 11289600;
335 break;
336 case 8000:
337 case 16000:
338 case 32000:
339 case 48000:
340 case 64000:
341 case 96000:
342 mclk = 12288000;
343 break;
344 default:
345 return -EINVAL;
346 }
347 min_mclk = 128 * srate;
348
349 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
350 if (err < 0) {
351 if (!(machine->util_data.set_mclk % min_mclk))
352 mclk = machine->util_data.set_mclk;
353 else {
354 dev_err(card->dev, "Can't configure clocks\n");
355 return err;
356 }
357 }
358
359 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
360
361 return 0;
362}
363
364static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
365 struct snd_pcm_hw_params *params)
366{
367 struct snd_soc_pcm_runtime *rtd = substream->private_data;
368#ifndef CONFIG_ARCH_TEGRA_2x_SOC
369 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
370#endif
371 struct snd_soc_card *card = rtd->card;
372 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
373 int err, srate, mclk, min_mclk, sample_size;
374
375 switch (params_format(params)) {
376 case SNDRV_PCM_FORMAT_S16_LE:
377 sample_size = 16;
378 break;
379 default:
380 return -EINVAL;
381 }
382
383 srate = params_rate(params);
384 switch (srate) {
385 case 11025:
386 case 22050:
387 case 44100:
388 case 88200:
389 mclk = 11289600;
390 break;
391 case 8000:
392 case 16000:
393 case 32000:
394 case 48000:
395 case 64000:
396 case 96000:
397 mclk = 12288000;
398 break;
399 default:
400 return -EINVAL;
401 }
402 min_mclk = 64 * srate;
403
404 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
405 if (err < 0) {
406 if (!(machine->util_data.set_mclk % min_mclk))
407 mclk = machine->util_data.set_mclk;
408 else {
409 dev_err(card->dev, "Can't configure clocks\n");
410 return err;
411 }
412 }
413
414 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
415
416 err = snd_soc_dai_set_fmt(rtd->cpu_dai,
417 SND_SOC_DAIFMT_DSP_A |
418 SND_SOC_DAIFMT_NB_NF |
419 SND_SOC_DAIFMT_CBS_CFS);
420 if (err < 0) {
421 dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
422 return err;
423 }
424
425#ifndef CONFIG_ARCH_TEGRA_2x_SOC
426 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
427 tegra_max98088_set_dam_cif(i2s->dam_ifc, params_rate(params),
428 params_channels(params), sample_size, 0, 0, 0, 0);
429#endif
430
431 return 0;
432}
433
434static int tegra_hw_free(struct snd_pcm_substream *substream)
435{
436 struct snd_soc_pcm_runtime *rtd = substream->private_data;
437 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(rtd->card);
438
439 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
440
441 return 0;
442}
443
444#ifndef CONFIG_ARCH_TEGRA_2x_SOC
445static int tegra_max98088_startup(struct snd_pcm_substream *substream)
446{
447 struct snd_soc_pcm_runtime *rtd = substream->private_data;
448 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
449 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
450 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(rtd->card);
451 struct codec_config *codec_info;
452 struct codec_config *bb_info;
453 int codec_index;
454
455 if (!i2s->is_dam_used)
456 return 0;
457
458 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
459 /*dam configuration*/
460 if (!i2s->dam_ch_refcount)
461 i2s->dam_ifc = tegra30_dam_allocate_controller();
462
463 tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
464 i2s->dam_ch_refcount++;
465 tegra30_dam_enable_clock(i2s->dam_ifc);
466
467 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
468 (i2s->dam_ifc*2), i2s->txcif);
469
470 /*
471 *make the dam tx to i2s rx connection if this is the only client
472 *using i2s for playback
473 */
474 if (i2s->playback_ref_count == 1)
475 tegra30_ahub_set_rx_cif_source(
476 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
477 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
478
479 /* enable the dam*/
480 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
481 TEGRA30_DAM_CHIN1);
482 } else {
483
484 i2s->is_call_mode_rec = machine->is_call_mode;
485
486 if (!i2s->is_call_mode_rec)
487 return 0;
488
489 if (machine->is_device_bt)
490 codec_index = BT_SCO;
491 else
492 codec_index = HIFI_CODEC;
493
494 codec_info = &machine->codec_info[codec_index];
495 bb_info = &machine->codec_info[BASEBAND];
496
497 /* allocate a dam for voice call recording */
498
499 i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();
500 tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
501 TEGRA30_DAM_CHIN0_SRC);
502 tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
503 TEGRA30_DAM_CHIN1);
504 tegra30_dam_enable_clock(i2s->call_record_dam_ifc);
505
506 /* configure the dam */
507 tegra_max98088_set_dam_cif(i2s->call_record_dam_ifc,
508 codec_info->rate, codec_info->channels,
509 codec_info->bitsize, 1, bb_info->rate,
510 bb_info->channels, bb_info->bitsize);
511
512 /* setup the connections for voice call record */
513
514 tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
515 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
516 (i2s->call_record_dam_ifc*2),
517 TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
518 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
519 (i2s->call_record_dam_ifc*2),
520 TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
521 tegra30_ahub_set_rx_cif_source(i2s->rxcif,
522 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
523
524 /* enable the dam*/
525
526 tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
527 TEGRA30_DAM_CHIN1);
528 tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
529 TEGRA30_DAM_CHIN0_SRC);
530 }
531
532 return 0;
533}
534
535static void tegra_max98088_shutdown(struct snd_pcm_substream *substream)
536{
537 struct snd_soc_pcm_runtime *rtd = substream->private_data;
538 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
539 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
540
541 if (!i2s->is_dam_used)
542 return;
543
544 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
545 /* disable the dam*/
546 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
547 TEGRA30_DAM_CHIN1);
548
549 /* disconnect the ahub connections*/
550 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
551 (i2s->dam_ifc*2));
552
553 /* disable the dam and free the controller */
554 tegra30_dam_disable_clock(i2s->dam_ifc);
555 tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
556 i2s->dam_ch_refcount--;
557 if (!i2s->dam_ch_refcount)
558 tegra30_dam_free_controller(i2s->dam_ifc);
559 } else {
560
561 if (!i2s->is_call_mode_rec)
562 return 0;
563
564 i2s->is_call_mode_rec = 0;
565
566 /* disable the dam*/
567 tegra30_dam_enable(i2s->call_record_dam_ifc,
568 TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
569 tegra30_dam_enable(i2s->call_record_dam_ifc,
570 TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
571
572 /* disconnect the ahub connections*/
573 tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
574 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
575 (i2s->call_record_dam_ifc*2));
576 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
577 (i2s->call_record_dam_ifc*2));
578
579 /* free the dam channels and dam controller */
580 tegra30_dam_disable_clock(i2s->call_record_dam_ifc);
581 tegra30_dam_free_channel(i2s->call_record_dam_ifc,
582 TEGRA30_DAM_CHIN1);
583 tegra30_dam_free_channel(i2s->call_record_dam_ifc,
584 TEGRA30_DAM_CHIN0_SRC);
585 tegra30_dam_free_controller(i2s->call_record_dam_ifc);
586 }
587
588 return;
589}
590#endif
591
592static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
593 struct snd_pcm_hw_params *params)
594{
595 struct snd_soc_pcm_runtime *rtd = substream->private_data;
596 struct snd_soc_dai *codec_dai = rtd->codec_dai;
597 struct snd_soc_codec *codec = rtd->codec;
598 struct snd_soc_card *card = codec->card;
599 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
600 int srate, mclk;
601 int err;
602
603 srate = params_rate(params);
604 switch (srate) {
605 case 8000:
606 case 16000:
607 case 24000:
608 case 32000:
609 case 48000:
610 case 64000:
611 case 96000:
612 mclk = 12288000;
613 break;
614 case 11025:
615 case 22050:
616 case 44100:
617 case 88200:
618 mclk = 11289600;
619 break;
620 default:
621 return -EINVAL;
622 break;
623 }
624
625 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
626 if (err < 0) {
627 if (!(machine->util_data.set_mclk % mclk))
628 mclk = machine->util_data.set_mclk;
629 else {
630 dev_err(card->dev, "Can't configure clocks\n");
631 return err;
632 }
633 }
634
635 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
636
637 err = snd_soc_dai_set_fmt(codec_dai,
638 SND_SOC_DAIFMT_I2S |
639 SND_SOC_DAIFMT_NB_NF |
640 SND_SOC_DAIFMT_CBS_CFS);
641 if (err < 0) {
642 dev_err(card->dev, "codec_dai fmt not set\n");
643 return err;
644 }
645
646 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
647 SND_SOC_CLOCK_IN);
648 if (err < 0) {
649 dev_err(card->dev, "codec_dai clock not set\n");
650 return err;
651 }
652
653#ifndef CONFIG_ARCH_TEGRA_2x_SOC
654 /* codec configuration */
655 machine->codec_info[HIFI_CODEC].rate = params_rate(params);
656 machine->codec_info[HIFI_CODEC].channels = params_channels(params);
657 machine->codec_info[HIFI_CODEC].bitsize = 16;
658 machine->codec_info[HIFI_CODEC].is_i2smaster = 1;
659 machine->codec_info[HIFI_CODEC].is_format_dsp = 0;
660
661 /* baseband configuration */
662 machine->codec_info[BASEBAND].bitsize = 16;
663 machine->codec_info[BASEBAND].is_i2smaster = 1;
664 machine->codec_info[BASEBAND].is_format_dsp = 1;
665#endif
666
667 machine->is_device_bt = 0;
668
669 return 0;
670}
671
672static void tegra_voice_call_shutdown(struct snd_pcm_substream *substream)
673{
674 struct snd_soc_pcm_runtime *rtd = substream->private_data;
675 struct tegra_max98088 *machine =
676 snd_soc_card_get_drvdata(rtd->codec->card);
677
678#ifndef CONFIG_ARCH_TEGRA_2x_SOC
679 machine->codec_info[HIFI_CODEC].rate = 0;
680 machine->codec_info[HIFI_CODEC].channels = 0;
681#endif
682
683 return;
684}
685
686static int tegra_bt_voice_call_hw_params(struct snd_pcm_substream *substream,
687 struct snd_pcm_hw_params *params)
688{
689 struct snd_soc_pcm_runtime *rtd = substream->private_data;
690 struct snd_soc_card *card = rtd->card;
691 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
692 int err, srate, mclk, min_mclk;
693
694 srate = params_rate(params);
695 switch (srate) {
696 case 11025:
697 case 22050:
698 case 44100:
699 case 88200:
700 mclk = 11289600;
701 break;
702 case 8000:
703 case 16000:
704 case 32000:
705 case 48000:
706 case 64000:
707 case 96000:
708 mclk = 12288000;
709 break;
710 default:
711 return -EINVAL;
712 }
713 min_mclk = 64 * srate;
714
715 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
716 if (err < 0) {
717 if (!(machine->util_data.set_mclk % min_mclk))
718 mclk = machine->util_data.set_mclk;
719 else {
720 dev_err(card->dev, "Can't configure clocks\n");
721 return err;
722 }
723 }
724
725 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
726
727#ifndef CONFIG_ARCH_TEGRA_2x_SOC
728 /* codec configuration */
729 machine->codec_info[BT_SCO].rate = params_rate(params);
730 machine->codec_info[BT_SCO].channels = params_channels(params);
731 machine->codec_info[BT_SCO].bitsize = 16;
732 machine->codec_info[BT_SCO].is_i2smaster = 1;
733 machine->codec_info[BT_SCO].is_format_dsp = 1;
734
735 /* baseband configuration */
736 machine->codec_info[BASEBAND].bitsize = 16;
737 machine->codec_info[BASEBAND].is_i2smaster = 1;
738 machine->codec_info[BASEBAND].is_format_dsp = 1;
739#endif
740
741 machine->is_device_bt = 1;
742
743 return 0;
744}
745
746static void tegra_bt_voice_call_shutdown(struct snd_pcm_substream *substream)
747{
748 struct snd_soc_pcm_runtime *rtd = substream->private_data;
749 struct tegra_max98088 *machine =
750 snd_soc_card_get_drvdata(rtd->codec->card);
751
752#ifndef CONFIG_ARCH_TEGRA_2x_SOC
753 machine->codec_info[BT_SCO].rate = 0;
754 machine->codec_info[BT_SCO].channels = 0;
755#endif
756
757 return;
758}
759
760static struct snd_soc_ops tegra_max98088_ops = {
761 .hw_params = tegra_max98088_hw_params,
762 .hw_free = tegra_hw_free,
763#ifndef CONFIG_ARCH_TEGRA_2x_SOC
764 .startup = tegra_max98088_startup,
765 .shutdown = tegra_max98088_shutdown,
766#endif
767};
768
769static struct snd_soc_ops tegra_spdif_ops = {
770 .hw_params = tegra_spdif_hw_params,
771 .hw_free = tegra_hw_free,
772};
773
774static struct snd_soc_ops tegra_voice_call_ops = {
775 .hw_params = tegra_voice_call_hw_params,
776 .shutdown = tegra_voice_call_shutdown,
777 .hw_free = tegra_hw_free,
778};
779
780static struct snd_soc_ops tegra_bt_voice_call_ops = {
781 .hw_params = tegra_bt_voice_call_hw_params,
782 .shutdown = tegra_bt_voice_call_shutdown,
783 .hw_free = tegra_hw_free,
784};
785
786static struct snd_soc_ops tegra_bt_ops = {
787 .hw_params = tegra_bt_hw_params,
788 .hw_free = tegra_hw_free,
789#ifndef CONFIG_ARCH_TEGRA_2x_SOC
790 .startup = tegra_max98088_startup,
791 .shutdown = tegra_max98088_shutdown,
792#endif
793};
794
795static struct snd_soc_jack tegra_max98088_hp_jack;
796
797#ifdef CONFIG_SWITCH
798static struct switch_dev wired_switch_dev = {
799 .name = "h2w",
800};
801
802/* These values are copied from WiredAccessoryObserver */
803enum headset_state {
804 BIT_NO_HEADSET = 0,
805 BIT_HEADSET = (1 << 0),
806 BIT_HEADSET_NO_MIC = (1 << 1),
807};
808
809static int headset_switch_notify(struct notifier_block *self,
810 unsigned long action, void *dev)
811{
812 int state = 0;
813
814 switch (action) {
815 case SND_JACK_HEADPHONE:
816 state |= BIT_HEADSET_NO_MIC;
817 break;
818 case SND_JACK_HEADSET:
819 state |= BIT_HEADSET;
820 break;
821 default:
822 state |= BIT_NO_HEADSET;
823 }
824
825 switch_set_state(&wired_switch_dev, state);
826
827 return NOTIFY_OK;
828}
829
830static struct notifier_block headset_switch_nb = {
831 .notifier_call = headset_switch_notify,
832};
833#else
834static struct snd_soc_jack_pin tegra_max98088_hp_jack_pins[] = {
835 {
836 .pin = "Headphone Jack",
837 .mask = SND_JACK_HEADPHONE,
838 },
839};
840#endif
841
842static int tegra_max98088_event_int_spk(struct snd_soc_dapm_widget *w,
843 struct snd_kcontrol *k, int event)
844{
845 struct snd_soc_dapm_context *dapm = w->dapm;
846 struct snd_soc_card *card = dapm->card;
847 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
848 struct tegra_asoc_platform_data *pdata = machine->pdata;
849
850 if (!(machine->gpio_requested & GPIO_SPKR_EN))
851 return 0;
852
853 gpio_set_value_cansleep(pdata->gpio_spkr_en,
854 SND_SOC_DAPM_EVENT_ON(event));
855
856 return 0;
857}
858
859static int tegra_max98088_event_hp(struct snd_soc_dapm_widget *w,
860 struct snd_kcontrol *k, int event)
861{
862 struct snd_soc_dapm_context *dapm = w->dapm;
863 struct snd_soc_card *card = dapm->card;
864 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
865 struct tegra_asoc_platform_data *pdata = machine->pdata;
866
867 if (!(machine->gpio_requested & GPIO_HP_MUTE))
868 return 0;
869
870 gpio_set_value_cansleep(pdata->gpio_hp_mute,
871 !SND_SOC_DAPM_EVENT_ON(event));
872
873 return 0;
874}
875
876static const struct snd_soc_dapm_widget tegra_max98088_dapm_widgets[] = {
877 SND_SOC_DAPM_SPK("Int Spk", tegra_max98088_event_int_spk),
878 SND_SOC_DAPM_OUTPUT("Earpiece"),
879 SND_SOC_DAPM_HP("Headphone Jack", tegra_max98088_event_hp),
880 SND_SOC_DAPM_MIC("Mic Jack", NULL),
881 SND_SOC_DAPM_INPUT("Int Mic"),
882};
883
884static const struct snd_soc_dapm_route enterprise_audio_map[] = {
885 {"Int Spk", NULL, "SPKL"},
886 {"Int Spk", NULL, "SPKR"},
887 {"Earpiece", NULL, "RECL"},
888 {"Earpiece", NULL, "RECR"},
889 {"Headphone Jack", NULL, "HPL"},
890 {"Headphone Jack", NULL, "HPR"},
891 {"MICBIAS", NULL, "Mic Jack"},
892 {"MIC2", NULL, "MICBIAS"},
893 {"MICBIAS", NULL, "Int Mic"},
894 {"MIC1", NULL, "MICBIAS"},
895};
896
897static const struct snd_kcontrol_new tegra_max98088_controls[] = {
898 SOC_DAPM_PIN_SWITCH("Int Spk"),
899 SOC_DAPM_PIN_SWITCH("Earpiece"),
900 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
901 SOC_DAPM_PIN_SWITCH("Mic Jack"),
902 SOC_DAPM_PIN_SWITCH("Int Mic"),
903};
904
905static int tegra_max98088_init(struct snd_soc_pcm_runtime *rtd)
906{
907 struct snd_soc_codec *codec = rtd->codec;
908 struct snd_soc_dapm_context *dapm = &codec->dapm;
909 struct snd_soc_card *card = codec->card;
910 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
911 struct tegra_asoc_platform_data *pdata = machine->pdata;
912#ifndef CONFIG_ARCH_TEGRA_2x_SOC
913 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
914#endif
915 int ret;
916
917#ifndef CONFIG_ARCH_TEGRA_2x_SOC
918 if (machine->codec_info[BASEBAND].i2s_id != -1)
919 i2s->is_dam_used = true;
920#endif
921
922 if (machine->init_done)
923 return 0;
924
925 machine->init_done = true;
926
927 machine->pcard = card;
928 machine->bias_level = SND_SOC_BIAS_STANDBY;
929
930 if (gpio_is_valid(pdata->gpio_spkr_en)) {
931 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
932 if (ret) {
933 dev_err(card->dev, "cannot get spkr_en gpio\n");
934 return ret;
935 }
936 machine->gpio_requested |= GPIO_SPKR_EN;
937
938 gpio_direction_output(pdata->gpio_spkr_en, 0);
939 }
940
941 if (gpio_is_valid(pdata->gpio_hp_mute)) {
942 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
943 if (ret) {
944 dev_err(card->dev, "cannot get hp_mute gpio\n");
945 return ret;
946 }
947 machine->gpio_requested |= GPIO_HP_MUTE;
948
949 gpio_direction_output(pdata->gpio_hp_mute, 0);
950 }
951
952 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
953 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
954 if (ret) {
955 dev_err(card->dev, "cannot get int_mic_en gpio\n");
956 return ret;
957 }
958 machine->gpio_requested |= GPIO_INT_MIC_EN;
959
960 /* Disable int mic; enable signal is active-high */
961 gpio_direction_output(pdata->gpio_int_mic_en, 0);
962 }
963
964 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
965 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
966 if (ret) {
967 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
968 return ret;
969 }
970 machine->gpio_requested |= GPIO_EXT_MIC_EN;
971
972 /* Enable ext mic; enable signal is active-low */
973 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
974 }
975
976 ret = snd_soc_add_controls(codec, tegra_max98088_controls,
977 ARRAY_SIZE(tegra_max98088_controls));
978 if (ret < 0)
979 return ret;
980
981 snd_soc_dapm_new_controls(dapm, tegra_max98088_dapm_widgets,
982 ARRAY_SIZE(tegra_max98088_dapm_widgets));
983
984 snd_soc_dapm_add_routes(dapm, enterprise_audio_map,
985 ARRAY_SIZE(enterprise_audio_map));
986
987 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
988 &tegra_max98088_hp_jack);
989 if (ret < 0)
990 return ret;
991
992#ifdef CONFIG_SWITCH
993 snd_soc_jack_notifier_register(&tegra_max98088_hp_jack,
994 &headset_switch_nb);
995#else /*gpio based headset detection*/
996 snd_soc_jack_add_pins(&tegra_max98088_hp_jack,
997 ARRAY_SIZE(tegra_max98088_hp_jack_pins),
998 tegra_max98088_hp_jack_pins);
999#endif
1000
1001 max98088_headset_detect(codec, &tegra_max98088_hp_jack,
1002 SND_JACK_HEADSET);
1003
1004 /* Add call mode switch control */
1005 ret = snd_ctl_add(codec->card->snd_card,
1006 snd_ctl_new1(&tegra_call_mode_control, machine));
1007 if (ret < 0)
1008 return ret;
1009
1010 snd_soc_dapm_nc_pin(dapm, "INA1");
1011 snd_soc_dapm_nc_pin(dapm, "INA2");
1012 snd_soc_dapm_nc_pin(dapm, "INB1");
1013 snd_soc_dapm_nc_pin(dapm, "INB2");
1014 snd_soc_dapm_sync(dapm);
1015
1016 return 0;
1017}
1018
1019static struct snd_soc_dai_link tegra_max98088_dai[NUM_DAI_LINKS] = {
1020 [DAI_LINK_HIFI] = {
1021 .name = "MAX98088",
1022 .stream_name = "MAX98088 HIFI",
1023 .codec_name = "max98088.0-0010",
1024 .platform_name = "tegra-pcm-audio",
1025 .codec_dai_name = "HiFi",
1026 .init = tegra_max98088_init,
1027 .ops = &tegra_max98088_ops,
1028 },
1029 [DAI_LINK_SPDIF] = {
1030 .name = "SPDIF",
1031 .stream_name = "SPDIF PCM",
1032 .codec_name = "spdif-dit.0",
1033 .platform_name = "tegra-pcm-audio",
1034 .cpu_dai_name = "tegra30-spdif",
1035 .codec_dai_name = "dit-hifi",
1036 .ops = &tegra_spdif_ops,
1037 },
1038 [DAI_LINK_BTSCO] = {
1039 .name = "BT SCO",
1040 .stream_name = "BT SCO PCM",
1041 .codec_name = "spdif-dit.1",
1042 .platform_name = "tegra-pcm-audio",
1043 .codec_dai_name = "dit-hifi",
1044 .init = tegra_max98088_init,
1045 .ops = &tegra_bt_ops,
1046 },
1047 [DAI_LINK_VOICE_CALL] = {
1048 .name = "VOICE CALL",
1049 .stream_name = "VOICE CALL PCM",
1050 .codec_name = "max98088.0-0010",
1051 .platform_name = "tegra-pcm-audio",
1052 .cpu_dai_name = "dit-hifi",
1053 .codec_dai_name = "HiFi",
1054 .ops = &tegra_voice_call_ops,
1055 },
1056 [DAI_LINK_BT_VOICE_CALL] = {
1057 .name = "BT VOICE CALL",
1058 .stream_name = "BT VOICE CALL PCM",
1059 .codec_name = "spdif-dit.2",
1060 .platform_name = "tegra-pcm-audio",
1061 .cpu_dai_name = "dit-hifi",
1062 .codec_dai_name = "dit-hifi",
1063 .ops = &tegra_bt_voice_call_ops,
1064 },
1065};
1066
1067static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
1068 enum snd_soc_bias_level level)
1069{
1070 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
1071
1072 if (machine->bias_level == SND_SOC_BIAS_OFF &&
1073 level != SND_SOC_BIAS_OFF)
1074 tegra_asoc_utils_clk_enable(&machine->util_data);
1075
1076 return 0;
1077}
1078
1079static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
1080 enum snd_soc_bias_level level)
1081{
1082 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
1083
1084 if (machine->bias_level != SND_SOC_BIAS_OFF &&
1085 level == SND_SOC_BIAS_OFF)
1086 tegra_asoc_utils_clk_disable(&machine->util_data);
1087
1088 machine->bias_level = level;
1089
1090 return 0 ;
1091}
1092
1093static struct snd_soc_card snd_soc_tegra_max98088 = {
1094 .name = "tegra-max98088",
1095 .dai_link = tegra_max98088_dai,
1096 .num_links = ARRAY_SIZE(tegra_max98088_dai),
1097 .set_bias_level = tegra30_soc_set_bias_level,
1098 .set_bias_level_post = tegra30_soc_set_bias_level_post,
1099};
1100
1101static __devinit int tegra_max98088_driver_probe(struct platform_device *pdev)
1102{
1103 struct snd_soc_card *card = &snd_soc_tegra_max98088;
1104 struct tegra_max98088 *machine;
1105 struct tegra_asoc_platform_data *pdata;
1106 int ret, i;
1107
1108 pdata = pdev->dev.platform_data;
1109 if (!pdata) {
1110 dev_err(&pdev->dev, "No platform data supplied\n");
1111 return -EINVAL;
1112 }
1113
1114 machine = kzalloc(sizeof(struct tegra_max98088), GFP_KERNEL);
1115 if (!machine) {
1116 dev_err(&pdev->dev, "Can't allocate tegra_max98088 struct\n");
1117 return -ENOMEM;
1118 }
1119
1120 machine->pdata = pdata;
1121
1122 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
1123 if (ret)
1124 goto err_free_machine;
1125
1126 card->dev = &pdev->dev;
1127 platform_set_drvdata(pdev, card);
1128 snd_soc_card_set_drvdata(card, machine);
1129
1130#ifdef CONFIG_SWITCH
1131 /* Add h2w switch class support */
1132 ret = switch_dev_register(&wired_switch_dev);
1133 if (ret < 0) {
1134 dev_err(&pdev->dev, "not able to register switch device\n");
1135 goto err_fini_utils;
1136 }
1137#endif
1138
1139#ifndef CONFIG_ARCH_TEGRA_2x_SOC
1140 for (i = 0; i < NUM_I2S_DEVICES ; i++)
1141 machine->codec_info[i].i2s_id = pdata->audio_port_id[i];
1142
1143 machine->codec_info[BASEBAND].rate = pdata->baseband_param.rate;
1144 machine->codec_info[BASEBAND].channels = pdata->baseband_param.channels;
1145
1146 tegra_max98088_dai[DAI_LINK_HIFI].cpu_dai_name =
1147 tegra_max98088_i2s_dai_name[machine->codec_info[HIFI_CODEC].i2s_id];
1148
1149 tegra_max98088_dai[DAI_LINK_BTSCO].cpu_dai_name =
1150 tegra_max98088_i2s_dai_name[machine->codec_info[BT_SCO].i2s_id];
1151#endif
1152
1153 ret = snd_soc_register_card(card);
1154 if (ret) {
1155 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
1156 ret);
1157 goto err_switch_unregister;
1158 }
1159
1160 if (!card->instantiated) {
1161 dev_err(&pdev->dev, "No MAX98088 codec\n");
1162 goto err_unregister_card;
1163 }
1164
1165 return 0;
1166
1167err_unregister_card:
1168 snd_soc_unregister_card(card);
1169err_switch_unregister:
1170#ifdef CONFIG_SWITCH
1171 switch_dev_unregister(&wired_switch_dev);
1172#endif
1173err_fini_utils:
1174 tegra_asoc_utils_fini(&machine->util_data);
1175err_free_machine:
1176 kfree(machine);
1177 return ret;
1178}
1179
1180static int __devexit tegra_max98088_driver_remove(struct platform_device *pdev)
1181{
1182 struct snd_soc_card *card = platform_get_drvdata(pdev);
1183 struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
1184 struct tegra_asoc_platform_data *pdata = machine->pdata;
1185
1186 snd_soc_unregister_card(card);
1187
1188#ifdef CONFIG_SWITCH
1189 switch_dev_unregister(&wired_switch_dev);
1190#endif
1191
1192 tegra_asoc_utils_fini(&machine->util_data);
1193
1194 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
1195 gpio_free(pdata->gpio_ext_mic_en);
1196 if (machine->gpio_requested & GPIO_INT_MIC_EN)
1197 gpio_free(pdata->gpio_int_mic_en);
1198 if (machine->gpio_requested & GPIO_HP_MUTE)
1199 gpio_free(pdata->gpio_hp_mute);
1200 if (machine->gpio_requested & GPIO_SPKR_EN)
1201 gpio_free(pdata->gpio_spkr_en);
1202
1203 kfree(machine);
1204
1205 return 0;
1206}
1207
1208static struct platform_driver tegra_max98088_driver = {
1209 .driver = {
1210 .name = DRV_NAME,
1211 .owner = THIS_MODULE,
1212 .pm = &snd_soc_pm_ops,
1213 },
1214 .probe = tegra_max98088_driver_probe,
1215 .remove = __devexit_p(tegra_max98088_driver_remove),
1216};
1217
1218static int __init tegra_max98088_modinit(void)
1219{
1220 return platform_driver_register(&tegra_max98088_driver);
1221}
1222module_init(tegra_max98088_modinit);
1223
1224static void __exit tegra_max98088_modexit(void)
1225{
1226 platform_driver_unregister(&tegra_max98088_driver);
1227}
1228module_exit(tegra_max98088_modexit);
1229
1230MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
1231MODULE_DESCRIPTION("Tegra+MAX98088 machine ASoC driver");
1232MODULE_LICENSE("GPL");
1233MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c
new file mode 100644
index 00000000000..2104ba849cd
--- /dev/null
+++ b/sound/soc/tegra/tegra_max98095.c
@@ -0,0 +1,723 @@
1/*
2 * tegra_max98095.c - Tegra machine ASoC driver for boards using MAX98095 codec.
3 *
4 * Author: Ravindra Lokhande <rlokhande@nvidia.com>
5 * Copyright (C) 2012 - NVIDIA, Inc.
6 *
7 * Based on version from Sumit Bhattacharya <sumitb@nvidia.com>
8 *
9 * Based on code copyright/by:
10 *
11 * (c) 2010, 2011, 2012 Nvidia Graphics Pvt. Ltd.
12 *
13 * Copyright 2007 Wolfson Microelectronics PLC.
14 * Author: Graeme Gregory
15 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * version 2 as published by the Free Software Foundation.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
29 * 02110-1301 USA
30 *
31 */
32
33#include <asm/mach-types.h>
34
35#include <linux/module.h>
36#include <linux/platform_device.h>
37#include <linux/slab.h>
38#include <linux/gpio.h>
39#include <linux/regulator/consumer.h>
40#ifdef CONFIG_SWITCH
41#include <linux/switch.h>
42#endif
43
44#include <mach/tegra_asoc_pdata.h>
45
46#include <sound/core.h>
47#include <sound/jack.h>
48#include <sound/pcm.h>
49#include <sound/pcm_params.h>
50#include <sound/soc.h>
51
52#include "../codecs/max98095.h"
53
54#include "tegra_pcm.h"
55#include "tegra_asoc_utils.h"
56#ifndef CONFIG_ARCH_TEGRA_2x_SOC
57#include "tegra30_ahub.h"
58#include "tegra30_i2s.h"
59#include "tegra30_dam.h"
60#endif
61
62#define DRV_NAME "tegra-snd-max98095"
63
64#define GPIO_SPKR_EN BIT(0)
65#define GPIO_HP_MUTE BIT(1)
66#define GPIO_INT_MIC_EN BIT(2)
67#define GPIO_EXT_MIC_EN BIT(3)
68
69#ifndef CONFIG_ARCH_TEGRA_2x_SOC
70const char *tegra_max98095_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
71 "tegra30-i2s.0",
72 "tegra30-i2s.1",
73 "tegra30-i2s.2",
74 "tegra30-i2s.3",
75 "tegra30-i2s.4",
76};
77#endif
78
79struct tegra_max98095 {
80 struct tegra_asoc_utils_data util_data;
81 struct tegra_asoc_platform_data *pdata;
82 int gpio_requested;
83 bool init_done;
84 int is_call_mode;
85 int is_device_bt;
86#ifndef CONFIG_ARCH_TEGRA_2x_SOC
87 struct codec_config codec_info[NUM_I2S_DEVICES];
88#endif
89 enum snd_soc_bias_level bias_level;
90};
91
92
93#ifndef CONFIG_ARCH_TEGRA_2x_SOC
94static int tegra_max98095_set_dam_cif(int dam_ifc, int srate,
95 int channels, int bit_size)
96{
97 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHOUT,
98 srate);
99 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN1,
100 srate);
101 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN1,
102 channels, bit_size, channels,
103 bit_size);
104 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHOUT,
105 channels, bit_size, channels,
106 bit_size);
107
108 return 0;
109}
110#endif
111
112static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
113 struct snd_pcm_hw_params *params)
114{
115 struct snd_soc_pcm_runtime *rtd = substream->private_data;
116 struct snd_soc_dai *codec_dai = rtd->codec_dai;
117 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
118 struct snd_soc_codec *codec = rtd->codec;
119 struct snd_soc_card *card = codec->card;
120 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
121#ifndef CONFIG_ARCH_TEGRA_2x_SOC
122 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
123#endif
124 unsigned int srate, mclk, sample_size;
125 int err;
126
127 switch (params_format(params)) {
128 case SNDRV_PCM_FORMAT_S16_LE:
129 sample_size = 16;
130 break;
131 default:
132 return -EINVAL;
133 }
134
135 srate = params_rate(params);
136 switch (srate) {
137 case 8000:
138 case 16000:
139 case 24000:
140 case 32000:
141 case 48000:
142 case 64000:
143 case 96000:
144 mclk = 12288000;
145 break;
146 case 11025:
147 case 22050:
148 case 44100:
149 case 88200:
150 mclk = 11289600;
151 break;
152 default:
153 mclk = 12000000;
154 break;
155 }
156
157 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
158 if (err < 0) {
159 if (!(machine->util_data.set_mclk % mclk))
160 mclk = machine->util_data.set_mclk;
161 else {
162 dev_err(card->dev, "Can't configure clocks\n");
163 return err;
164 }
165 }
166
167 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
168
169 err = snd_soc_dai_set_fmt(codec_dai,
170 SND_SOC_DAIFMT_I2S |
171 SND_SOC_DAIFMT_NB_NF |
172 SND_SOC_DAIFMT_CBS_CFS);
173 if (err < 0) {
174 dev_err(card->dev, "codec_dai fmt not set\n");
175 return err;
176 }
177
178 err = snd_soc_dai_set_fmt(cpu_dai,
179 SND_SOC_DAIFMT_I2S |
180 SND_SOC_DAIFMT_NB_NF |
181 SND_SOC_DAIFMT_CBS_CFS);
182 if (err < 0) {
183 dev_err(card->dev, "cpu_dai fmt not set\n");
184 return err;
185 }
186
187 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
188 SND_SOC_CLOCK_IN);
189 if (err < 0) {
190 dev_err(card->dev, "codec_dai clock not set\n");
191 return err;
192 }
193
194#ifndef CONFIG_ARCH_TEGRA_2x_SOC
195 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
196 tegra_max98095_set_dam_cif(i2s->dam_ifc, srate,
197 params_channels(params), sample_size);
198#endif
199
200 return 0;
201}
202
203static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
204 struct snd_pcm_hw_params *params)
205{
206 struct snd_soc_pcm_runtime *rtd = substream->private_data;
207 struct snd_soc_card *card = rtd->card;
208 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
209 unsigned int srate, mclk, min_mclk;
210 int err;
211
212 srate = params_rate(params);
213 switch (srate) {
214 case 11025:
215 case 22050:
216 case 44100:
217 case 88200:
218 mclk = 11289600;
219 break;
220 case 8000:
221 case 16000:
222 case 32000:
223 case 48000:
224 case 64000:
225 case 96000:
226 mclk = 12288000;
227 break;
228 default:
229 return -EINVAL;
230 }
231 min_mclk = 128 * srate;
232
233 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
234 if (err < 0) {
235 if (!(machine->util_data.set_mclk % min_mclk))
236 mclk = machine->util_data.set_mclk;
237 else {
238 dev_err(card->dev, "Can't configure clocks\n");
239 return err;
240 }
241 }
242
243 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
244
245
246
247 return 0;
248}
249
250static int tegra_hw_free(struct snd_pcm_substream *substream)
251{
252 struct snd_soc_pcm_runtime *rtd = substream->private_data;
253 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(rtd->card);
254
255 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
256
257 return 0;
258}
259
260#ifndef CONFIG_ARCH_TEGRA_2x_SOC
261static int tegra_max98095_startup(struct snd_pcm_substream *substream)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
265 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
266
267 if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
268 !(i2s->is_dam_used))
269 return 0;
270
271 /*dam configuration*/
272 if (!i2s->dam_ch_refcount)
273 i2s->dam_ifc = tegra30_dam_allocate_controller();
274
275 tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
276 i2s->dam_ch_refcount++;
277 tegra30_dam_enable_clock(i2s->dam_ifc);
278 tegra30_dam_set_gain(i2s->dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
279
280 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
281 (i2s->dam_ifc*2), i2s->txcif);
282
283 /*
284 *make the dam tx to i2s rx connection if this is the only client
285 *using i2s for playback
286 */
287 if (i2s->playback_ref_count == 1)
288 tegra30_ahub_set_rx_cif_source(
289 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
290 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
291
292 /* enable the dam*/
293 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
294 TEGRA30_DAM_CHIN1);
295
296 return 0;
297}
298
299static void tegra_max98095_shutdown(struct snd_pcm_substream *substream)
300{
301 struct snd_soc_pcm_runtime *rtd = substream->private_data;
302 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
303 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
304
305 if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
306 !(i2s->is_dam_used))
307 return;
308
309 /* disable the dam*/
310 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
311 TEGRA30_DAM_CHIN1);
312
313 /* disconnect the ahub connections*/
314 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
315 (i2s->dam_ifc*2));
316
317 /* disable the dam and free the controller */
318 tegra30_dam_disable_clock(i2s->dam_ifc);
319 tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
320 i2s->dam_ch_refcount--;
321 if (!i2s->dam_ch_refcount)
322 tegra30_dam_free_controller(i2s->dam_ifc);
323
324 return;
325}
326#endif
327
328static struct snd_soc_ops tegra_max98095_ops = {
329 .hw_params = tegra_max98095_hw_params,
330 .hw_free = tegra_hw_free,
331#ifndef CONFIG_ARCH_TEGRA_2x_SOC
332 .startup = tegra_max98095_startup,
333 .shutdown = tegra_max98095_shutdown,
334#endif
335};
336
337static struct snd_soc_ops tegra_spdif_ops = {
338 .hw_params = tegra_spdif_hw_params,
339 .hw_free = tegra_hw_free,
340};
341
342static struct snd_soc_jack tegra_max98095_hp_jack;
343
344#ifdef CONFIG_SWITCH
345static struct switch_dev wired_switch_dev = {
346 .name = "h2w",
347};
348
349/* These values are copied from WiredAccessoryObserver */
350enum headset_state {
351 BIT_NO_HEADSET = 0,
352 BIT_HEADSET = (1 << 0),
353 BIT_HEADSET_NO_MIC = (1 << 1),
354};
355
356static int headset_switch_notify(struct notifier_block *self,
357 unsigned long action, void *dev)
358{
359 int state = 0;
360
361 switch (action) {
362 case SND_JACK_HEADPHONE:
363 state |= BIT_HEADSET_NO_MIC;
364 break;
365 case SND_JACK_HEADSET:
366 state |= BIT_HEADSET;
367 break;
368 default:
369 state |= BIT_NO_HEADSET;
370 }
371
372 switch_set_state(&wired_switch_dev, state);
373
374 return NOTIFY_OK;
375}
376
377static struct notifier_block headset_switch_nb = {
378 .notifier_call = headset_switch_notify,
379};
380#else
381static struct snd_soc_jack_pin tegra_max98095_hp_jack_pins[] = {
382 {
383 .pin = "Headphone Jack",
384 .mask = SND_JACK_HEADPHONE,
385 },
386};
387#endif
388
389static int tegra_max98095_event_int_spk(struct snd_soc_dapm_widget *w,
390 struct snd_kcontrol *k, int event)
391{
392 struct snd_soc_dapm_context *dapm = w->dapm;
393 struct snd_soc_card *card = dapm->card;
394 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
395 struct tegra_asoc_platform_data *pdata = machine->pdata;
396
397 if (!(machine->gpio_requested & GPIO_SPKR_EN))
398 return 0;
399
400 gpio_set_value_cansleep(pdata->gpio_spkr_en,
401 SND_SOC_DAPM_EVENT_ON(event));
402
403 return 0;
404}
405
406static int tegra_max98095_event_hp(struct snd_soc_dapm_widget *w,
407 struct snd_kcontrol *k, int event)
408{
409 struct snd_soc_dapm_context *dapm = w->dapm;
410 struct snd_soc_card *card = dapm->card;
411 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
412 struct tegra_asoc_platform_data *pdata = machine->pdata;
413
414 if (!(machine->gpio_requested & GPIO_HP_MUTE))
415 return 0;
416
417 gpio_set_value_cansleep(pdata->gpio_hp_mute,
418 !SND_SOC_DAPM_EVENT_ON(event));
419
420 return 0;
421}
422
423static const struct snd_soc_dapm_widget tegra_max98095_dapm_widgets[] = {
424 SND_SOC_DAPM_SPK("Int Spk", tegra_max98095_event_int_spk),
425 SND_SOC_DAPM_HP("Headphone Jack", tegra_max98095_event_hp),
426 SND_SOC_DAPM_MIC("Mic Jack", NULL),
427 SND_SOC_DAPM_INPUT("Int Mic"),
428 SND_SOC_DAPM_LINE("Line In", NULL),
429};
430
431static const struct snd_soc_dapm_route enterprise_audio_map[] = {
432 {"Int Spk", NULL, "SPKL"},
433 {"Int Spk", NULL, "SPKR"},
434 {"Headphone Jack", NULL, "HPL"},
435 {"Headphone Jack", NULL, "HPR"},
436 {"MICBIAS2", NULL, "Mic Jack"},
437 {"MIC2", NULL, "MICBIAS2"},
438 {"MIC1", NULL, "Int Mic"},
439 {"MIC1", NULL, "MICBIAS1"},
440 {"INB1", NULL, "Line In"},
441 {"INB2", NULL, "Line In"},
442};
443
444static const struct snd_kcontrol_new tegra_max98095_controls[] = {
445 SOC_DAPM_PIN_SWITCH("Int Spk"),
446 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
447 SOC_DAPM_PIN_SWITCH("Mic Jack"),
448 SOC_DAPM_PIN_SWITCH("Int Mic"),
449 SOC_DAPM_PIN_SWITCH("LineIn"),
450};
451
452static int tegra_max98095_init(struct snd_soc_pcm_runtime *rtd)
453{
454 struct snd_soc_codec *codec = rtd->codec;
455 struct snd_soc_dapm_context *dapm = &codec->dapm;
456 struct snd_soc_card *card = codec->card;
457 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
458 struct tegra_asoc_platform_data *pdata = machine->pdata;
459#ifndef CONFIG_ARCH_TEGRA_2x_SOC
460 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
461#endif
462 int ret;
463
464#ifndef CONFIG_ARCH_TEGRA_2x_SOC
465 if (machine->codec_info[BASEBAND].i2s_id != -1)
466 i2s->is_dam_used = true;
467#endif
468
469 if (machine->init_done)
470 return 0;
471
472 machine->init_done = true;
473
474 if (gpio_is_valid(pdata->gpio_spkr_en)) {
475 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
476 if (ret) {
477 dev_err(card->dev, "cannot get spkr_en gpio\n");
478 return ret;
479 }
480 machine->gpio_requested |= GPIO_SPKR_EN;
481
482 gpio_direction_output(pdata->gpio_spkr_en, 0);
483 }
484
485 if (gpio_is_valid(pdata->gpio_hp_mute)) {
486 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
487 if (ret) {
488 dev_err(card->dev, "cannot get hp_mute gpio\n");
489 return ret;
490 }
491 machine->gpio_requested |= GPIO_HP_MUTE;
492
493 gpio_direction_output(pdata->gpio_hp_mute, 0);
494 }
495
496 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
497 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
498 if (ret) {
499 dev_err(card->dev, "cannot get int_mic_en gpio\n");
500 return ret;
501 }
502 machine->gpio_requested |= GPIO_INT_MIC_EN;
503
504 /* Disable int mic; enable signal is active-high */
505 gpio_direction_output(pdata->gpio_int_mic_en, 0);
506 }
507
508 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
509 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
510 if (ret) {
511 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
512 return ret;
513 }
514 machine->gpio_requested |= GPIO_EXT_MIC_EN;
515
516 /* Enable ext mic; enable signal is active-low */
517 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
518 }
519
520 ret = snd_soc_add_controls(codec, tegra_max98095_controls,
521 ARRAY_SIZE(tegra_max98095_controls));
522 if (ret < 0)
523 return ret;
524
525 snd_soc_dapm_new_controls(dapm, tegra_max98095_dapm_widgets,
526 ARRAY_SIZE(tegra_max98095_dapm_widgets));
527
528 snd_soc_dapm_add_routes(dapm, enterprise_audio_map,
529 ARRAY_SIZE(enterprise_audio_map));
530
531 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
532 &tegra_max98095_hp_jack);
533 if (ret < 0)
534 return ret;
535
536#ifdef CONFIG_SWITCH
537 snd_soc_jack_notifier_register(&tegra_max98095_hp_jack,
538 &headset_switch_nb);
539#else /*gpio based headset detection*/
540 snd_soc_jack_add_pins(&tegra_max98095_hp_jack,
541 ARRAY_SIZE(tegra_max98095_hp_jack_pins),
542 tegra_max98095_hp_jack_pins);
543#endif
544
545 /* max98095_headset_detect(codec, &tegra_max98095_hp_jack,
546 SND_JACK_HEADSET); */
547
548 snd_soc_dapm_nc_pin(dapm, "INA1");
549 snd_soc_dapm_nc_pin(dapm, "INA2");
550 snd_soc_dapm_nc_pin(dapm, "INB1");
551 snd_soc_dapm_nc_pin(dapm, "INB2");
552 snd_soc_dapm_sync(dapm);
553
554 return 0;
555}
556
557static struct snd_soc_dai_link tegra_max98095_dai[] = {
558 {
559 .name = "MAX98095",
560 .stream_name = "MAX98095 HIFI",
561 .codec_name = "max98095.4-0010",
562 .platform_name = "tegra-pcm-audio",
563 .cpu_dai_name = "tegra30-i2s.1",
564 .codec_dai_name = "HiFi",
565 .init = tegra_max98095_init,
566 .ops = &tegra_max98095_ops,
567 },
568 {
569 .name = "SPDIF",
570 .stream_name = "SPDIF PCM",
571 .codec_name = "spdif-dit.0",
572 .platform_name = "tegra-pcm-audio",
573 .cpu_dai_name = "tegra30-spdif",
574 .codec_dai_name = "dit-hifi",
575 .ops = &tegra_spdif_ops,
576 },
577};
578
579static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
580 enum snd_soc_bias_level level)
581{
582 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
583
584 if (machine->bias_level == SND_SOC_BIAS_OFF &&
585 level != SND_SOC_BIAS_OFF)
586 tegra_asoc_utils_clk_enable(&machine->util_data);
587
588 machine->bias_level = level;
589
590 return 0;
591}
592
593static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
594 enum snd_soc_bias_level level)
595{
596 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
597
598 if (level == SND_SOC_BIAS_OFF)
599 tegra_asoc_utils_clk_disable(&machine->util_data);
600
601 return 0 ;
602}
603
604static struct snd_soc_card snd_soc_tegra_max98095 = {
605 .name = "tegra-max98095",
606 .dai_link = tegra_max98095_dai,
607 .num_links = ARRAY_SIZE(tegra_max98095_dai),
608 .set_bias_level = tegra30_soc_set_bias_level,
609 .set_bias_level_post = tegra30_soc_set_bias_level_post,
610};
611
612static __devinit int tegra_max98095_driver_probe(struct platform_device *pdev)
613{
614 struct snd_soc_card *card = &snd_soc_tegra_max98095;
615 struct tegra_max98095 *machine;
616 struct tegra_asoc_platform_data *pdata;
617 int ret;
618
619 pdata = pdev->dev.platform_data;
620 if (!pdata) {
621 dev_err(&pdev->dev, "No platform data supplied\n");
622 return -EINVAL;
623 }
624
625 machine = kzalloc(sizeof(struct tegra_max98095), GFP_KERNEL);
626 if (!machine) {
627 dev_err(&pdev->dev, "Can't allocate tegra_max98095 struct\n");
628 return -ENOMEM;
629 }
630
631 machine->pdata = pdata;
632
633 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
634 if (ret)
635 goto err_free_machine;
636
637 card->dev = &pdev->dev;
638 platform_set_drvdata(pdev, card);
639 snd_soc_card_set_drvdata(card, machine);
640
641#ifdef CONFIG_SWITCH
642 /* Add h2w switch class support */
643 ret = switch_dev_register(&wired_switch_dev);
644 if (ret < 0) {
645 dev_err(&pdev->dev, "not able to register switch device\n");
646 goto err_fini_utils;
647 }
648#endif
649
650 ret = snd_soc_register_card(card);
651 if (ret) {
652 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
653 ret);
654 goto err_switch_unregister;
655 }
656
657 return 0;
658
659err_switch_unregister:
660#ifdef CONFIG_SWITCH
661 switch_dev_unregister(&wired_switch_dev);
662#endif
663err_fini_utils:
664 tegra_asoc_utils_fini(&machine->util_data);
665err_free_machine:
666 kfree(machine);
667 return ret;
668}
669
670static int __devexit tegra_max98095_driver_remove(struct platform_device *pdev)
671{
672 struct snd_soc_card *card = platform_get_drvdata(pdev);
673 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
674 struct tegra_asoc_platform_data *pdata = machine->pdata;
675
676 snd_soc_unregister_card(card);
677
678#ifdef CONFIG_SWITCH
679 switch_dev_unregister(&wired_switch_dev);
680#endif
681
682 tegra_asoc_utils_fini(&machine->util_data);
683
684 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
685 gpio_free(pdata->gpio_ext_mic_en);
686 if (machine->gpio_requested & GPIO_INT_MIC_EN)
687 gpio_free(pdata->gpio_int_mic_en);
688 if (machine->gpio_requested & GPIO_HP_MUTE)
689 gpio_free(pdata->gpio_hp_mute);
690 if (machine->gpio_requested & GPIO_SPKR_EN)
691 gpio_free(pdata->gpio_spkr_en);
692
693 kfree(machine);
694
695 return 0;
696}
697
698static struct platform_driver tegra_max98095_driver = {
699 .driver = {
700 .name = DRV_NAME,
701 .owner = THIS_MODULE,
702 .pm = &snd_soc_pm_ops,
703 },
704 .probe = tegra_max98095_driver_probe,
705 .remove = __devexit_p(tegra_max98095_driver_remove),
706};
707
708static int __init tegra_max98095_modinit(void)
709{
710 return platform_driver_register(&tegra_max98095_driver);
711}
712module_init(tegra_max98095_modinit);
713
714static void __exit tegra_max98095_modexit(void)
715{
716 platform_driver_unregister(&tegra_max98095_driver);
717}
718module_exit(tegra_max98095_modexit);
719
720MODULE_AUTHOR("Ravindra Lokhande <rlokhande@nvidia.com>");
721MODULE_DESCRIPTION("Tegra+MAX98095 machine ASoC driver");
722MODULE_LICENSE("GPL");
723MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_p1852.c b/sound/soc/tegra/tegra_p1852.c
new file mode 100644
index 00000000000..27a1ea59034
--- /dev/null
+++ b/sound/soc/tegra/tegra_p1852.c
@@ -0,0 +1,272 @@
1/*
2 * tegra_p1852.c - Tegra machine ASoC driver for P1852 Boards.
3 *
4 * Author: Nitin Pai <npai@nvidia.com>
5 * Copyright (C) 2010-2012 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 * Copyright (c) 2009-2010, NVIDIA Corporation.
9 * Stephen Warren <swarren@nvidia.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 *
25 */
26
27#include <asm/mach-types.h>
28
29#include <linux/clk.h>
30#include <linux/module.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33
34#include <mach/tegra_p1852_pdata.h>
35
36#include <sound/core.h>
37#include <sound/pcm.h>
38#include <sound/pcm_params.h>
39#include <sound/soc.h>
40
41#include "tegra_pcm.h"
42#include "tegra_asoc_utils.h"
43
44#define DRV_NAME "tegra-snd-p1852"
45
46struct tegra_p1852 {
47 struct tegra_asoc_utils_data util_data;
48 struct tegra_p1852_platform_data *pdata;
49};
50
51static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
52 struct snd_pcm_hw_params *params)
53{
54 struct snd_soc_pcm_runtime *rtd = substream->private_data;
55 struct snd_soc_dai *codec_dai = rtd->codec_dai;
56 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
57 struct snd_soc_codec *codec = rtd->codec;
58 struct snd_soc_card *card = codec->card;
59 struct tegra_p1852 *machine = snd_soc_card_get_drvdata(card);
60 int srate, mclk;
61 int i2s_daifmt = 0;
62 int err;
63 struct tegra_p1852_platform_data *pdata;
64 int codec_id = codec_dai->id;
65
66 pdata = machine->pdata;
67
68 srate = params_rate(params);
69 switch (srate) {
70 case 64000:
71 case 88200:
72 case 96000:
73 mclk = 128 * srate;
74 break;
75 default:
76 mclk = 256 * srate;
77 break;
78 }
79
80 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
81 if (err < 0) {
82 if (!(machine->util_data.set_mclk % mclk))
83 mclk = machine->util_data.set_mclk;
84 else {
85 dev_err(card->dev, "Can't configure clocks\n");
86 return err;
87 }
88 }
89
90 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
91
92 if (pdata->codec_info[codec_id].master)
93 i2s_daifmt |= SND_SOC_DAIFMT_CBM_CFM;
94 else
95 i2s_daifmt |= SND_SOC_DAIFMT_CBS_CFS;
96
97 switch (pdata->codec_info[codec_id].i2s_format) {
98 case format_tdm:
99 i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
100 break;
101 case format_i2s:
102 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
103 break;
104 case format_rjm:
105 i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
106 break;
107 case format_ljm:
108 i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
109 break;
110 default:
111 break;
112 }
113
114 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
115 if (err < 0)
116 dev_info(card->dev, "codec_dai fmt not set\n");
117
118 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
119 if (err < 0) {
120 dev_err(card->dev, "cpu_dai fmt not set\n");
121 return err;
122 }
123
124 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
125 SND_SOC_CLOCK_IN);
126 if (err < 0)
127 dev_info(card->dev, "codec_dai clock not set\n");
128
129 return 0;
130}
131
132static int tegra_hw_free(struct snd_pcm_substream *substream)
133{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct tegra_p1852 *machine = snd_soc_card_get_drvdata(rtd->card);
136
137 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
138
139 return 0;
140}
141
142static struct snd_soc_ops tegra_p1852_ops = {
143 .hw_params = tegra_p1852_hw_params,
144 .hw_free = tegra_hw_free,
145};
146
147static struct snd_soc_dai_link tegra_p1852_dai_link[] = {
148 {
149 .name = "I2S-TDM-1",
150 .stream_name = "TEGRA PCM",
151 .platform_name = "tegra-pcm-audio",
152 .ops = &tegra_p1852_ops,
153 },
154 {
155 .name = "I2S-TDM-2",
156 .stream_name = "TEGRA PCM",
157 .platform_name = "tegra-pcm-audio",
158 .ops = &tegra_p1852_ops,
159 }
160};
161
162static struct snd_soc_card snd_soc_tegra_p1852 = {
163 .name = "tegra-p1852",
164 .dai_link = tegra_p1852_dai_link,
165 .num_links = ARRAY_SIZE(tegra_p1852_dai_link),
166};
167
168static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
169{
170 struct snd_soc_card *card = &snd_soc_tegra_p1852;
171 struct tegra_p1852 *machine;
172 struct tegra_p1852_platform_data *pdata;
173 int ret;
174 int i;
175
176 pdata = pdev->dev.platform_data;
177 if (!pdata) {
178 dev_err(&pdev->dev, "No platform data supplied\n");
179 return -EINVAL;
180 }
181
182 machine = kzalloc(sizeof(struct tegra_p1852), GFP_KERNEL);
183 if (!machine) {
184 dev_err(&pdev->dev, "Can't allocate tegra_p1852 struct\n");
185 return -ENOMEM;
186 }
187
188 machine->pdata = pdata;
189
190 /* The codec driver and codec dai have to come from the system
191 * level board configuration file
192 * */
193 for (i = 0; i < ARRAY_SIZE(tegra_p1852_dai_link); i++) {
194 tegra_p1852_dai_link[i].codec_name =
195 pdata->codec_info[i].codec_name;
196 tegra_p1852_dai_link[i].cpu_dai_name =
197 pdata->codec_info[i].cpu_dai_name;
198 tegra_p1852_dai_link[i].codec_dai_name =
199 pdata->codec_info[i].codec_dai_name;
200 tegra_p1852_dai_link[i].name =
201 pdata->codec_info[i].name;
202 }
203
204 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
205 if (ret)
206 goto err_free_machine;
207
208 card->dev = &pdev->dev;
209 platform_set_drvdata(pdev, card);
210 snd_soc_card_set_drvdata(card, machine);
211
212 ret = snd_soc_register_card(card);
213 if (ret) {
214 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
215 ret);
216 }
217
218 if (!card->instantiated) {
219 ret = -ENODEV;
220 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
221 ret);
222 goto err_unregister_card;
223 }
224
225 return 0;
226
227err_unregister_card:
228 snd_soc_unregister_card(card);
229 tegra_asoc_utils_fini(&machine->util_data);
230err_free_machine:
231 kfree(machine);
232 return ret;
233}
234
235static int __devexit tegra_p1852_driver_remove(struct platform_device *pdev)
236{
237 struct snd_soc_card *card = platform_get_drvdata(pdev);
238 struct tegra_p1852 *machine = snd_soc_card_get_drvdata(card);
239
240 snd_soc_unregister_card(card);
241 tegra_asoc_utils_fini(&machine->util_data);
242 kfree(machine);
243
244 return 0;
245}
246
247static struct platform_driver tegra_p1852_driver = {
248 .driver = {
249 .name = DRV_NAME,
250 .owner = THIS_MODULE,
251 .pm = &snd_soc_pm_ops,
252 },
253 .probe = tegra_p1852_driver_probe,
254 .remove = __devexit_p(tegra_p1852_driver_remove),
255};
256
257static int __init tegra_p1852_modinit(void)
258{
259 return platform_driver_register(&tegra_p1852_driver);
260}
261module_init(tegra_p1852_modinit);
262
263static void __exit tegra_p1852_modexit(void)
264{
265 platform_driver_unregister(&tegra_p1852_driver);
266}
267module_exit(tegra_p1852_modexit);
268
269MODULE_AUTHOR("Nitin Pai <npai@nvidia.com>");
270MODULE_DESCRIPTION("Tegra+P1852 machine ASoC driver");
271MODULE_LICENSE("GPL");
272MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 3c271f95358..f277d282fbd 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -48,9 +48,9 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
48 SNDRV_PCM_INFO_RESUME | 48 SNDRV_PCM_INFO_RESUME |
49 SNDRV_PCM_INFO_INTERLEAVED, 49 SNDRV_PCM_INFO_INTERLEAVED,
50 .formats = SNDRV_PCM_FMTBIT_S16_LE, 50 .formats = SNDRV_PCM_FMTBIT_S16_LE,
51 .channels_min = 2, 51 .channels_min = 1,
52 .channels_max = 2, 52 .channels_max = 2,
53 .period_bytes_min = 1024, 53 .period_bytes_min = 128,
54 .period_bytes_max = PAGE_SIZE, 54 .period_bytes_max = PAGE_SIZE,
55 .periods_min = 2, 55 .periods_min = 2,
56 .periods_max = 8, 56 .periods_max = 8,
@@ -147,28 +147,30 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
147 147
148 spin_lock_init(&prtd->lock); 148 spin_lock_init(&prtd->lock);
149 149
150 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 150 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
151 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
152 setup_dma_tx_request(&prtd->dma_req[0], dmap);
153 setup_dma_tx_request(&prtd->dma_req[1], dmap);
154 } else {
155 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
156 setup_dma_rx_request(&prtd->dma_req[0], dmap);
157 setup_dma_rx_request(&prtd->dma_req[1], dmap);
158 }
159 151
160 prtd->dma_req[0].dev = prtd; 152 if (dmap) {
161 prtd->dma_req[1].dev = prtd; 153 prtd->dma_req[0].dev = prtd;
154 prtd->dma_req[1].dev = prtd;
162 155
163 prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); 156 prtd->dma_chan = tegra_dma_allocate_channel(
164 if (prtd->dma_chan == NULL) { 157 TEGRA_DMA_MODE_CONTINUOUS_SINGLE,
165 ret = -ENOMEM; 158 "pcm");
166 goto err; 159 if (prtd->dma_chan == NULL) {
160 ret = -ENOMEM;
161 goto err;
162 }
167 } 163 }
168 164
169 /* Set HW params now that initialization is complete */ 165 /* Set HW params now that initialization is complete */
170 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); 166 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
171 167
168 /* Ensure period size is multiple of 8 */
169 ret = snd_pcm_hw_constraint_step(runtime, 0,
170 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8);
171 if (ret < 0)
172 goto err;
173
172 /* Ensure that buffer size is a multiple of period size */ 174 /* Ensure that buffer size is a multiple of period size */
173 ret = snd_pcm_hw_constraint_integer(runtime, 175 ret = snd_pcm_hw_constraint_integer(runtime,
174 SNDRV_PCM_HW_PARAM_PERIODS); 176 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -192,7 +194,8 @@ static int tegra_pcm_close(struct snd_pcm_substream *substream)
192 struct snd_pcm_runtime *runtime = substream->runtime; 194 struct snd_pcm_runtime *runtime = substream->runtime;
193 struct tegra_runtime_data *prtd = runtime->private_data; 195 struct tegra_runtime_data *prtd = runtime->private_data;
194 196
195 tegra_dma_free_channel(prtd->dma_chan); 197 if (prtd->dma_chan)
198 tegra_dma_free_channel(prtd->dma_chan);
196 199
197 kfree(prtd); 200 kfree(prtd);
198 201
@@ -204,9 +207,21 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
204{ 207{
205 struct snd_pcm_runtime *runtime = substream->runtime; 208 struct snd_pcm_runtime *runtime = substream->runtime;
206 struct tegra_runtime_data *prtd = runtime->private_data; 209 struct tegra_runtime_data *prtd = runtime->private_data;
210 struct snd_soc_pcm_runtime *rtd = substream->private_data;
211 struct tegra_pcm_dma_params * dmap;
207 212
208 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 213 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
209 214
215 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
216 if (dmap) {
217 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
218 setup_dma_tx_request(&prtd->dma_req[0], dmap);
219 setup_dma_tx_request(&prtd->dma_req[1], dmap);
220 } else {
221 setup_dma_rx_request(&prtd->dma_req[0], dmap);
222 setup_dma_rx_request(&prtd->dma_req[1], dmap);
223 }
224 }
210 prtd->dma_req[0].size = params_period_bytes(params); 225 prtd->dma_req[0].size = params_period_bytes(params);
211 prtd->dma_req[1].size = prtd->dma_req[0].size; 226 prtd->dma_req[1].size = prtd->dma_req[0].size;
212 227
@@ -261,10 +276,14 @@ static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream)
261{ 276{
262 struct snd_pcm_runtime *runtime = substream->runtime; 277 struct snd_pcm_runtime *runtime = substream->runtime;
263 struct tegra_runtime_data *prtd = runtime->private_data; 278 struct tegra_runtime_data *prtd = runtime->private_data;
279 int dma_transfer_count;
264 280
265 return prtd->period_index * runtime->period_size; 281 dma_transfer_count = tegra_dma_get_transfer_count(prtd->dma_chan,
266} 282 &prtd->dma_req[prtd->dma_req_idx]);
267 283
284 return prtd->period_index * runtime->period_size +
285 bytes_to_frames(runtime, dma_transfer_count);
286}
268 287
269static int tegra_pcm_mmap(struct snd_pcm_substream *substream, 288static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
270 struct vm_area_struct *vma) 289 struct vm_area_struct *vma)
@@ -309,9 +328,14 @@ static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
309 328
310static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) 329static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
311{ 330{
312 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 331 struct snd_pcm_substream *substream;
313 struct snd_dma_buffer *buf = &substream->dma_buffer; 332 struct snd_dma_buffer *buf;
333
334 substream = pcm->streams[stream].substream;
335 if (!substream)
336 return;
314 337
338 buf = &substream->dma_buffer;
315 if (!buf->area) 339 if (!buf->area)
316 return; 340 return;
317 341
@@ -322,9 +346,11 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
322 346
323static u64 tegra_dma_mask = DMA_BIT_MASK(32); 347static u64 tegra_dma_mask = DMA_BIT_MASK(32);
324 348
325static int tegra_pcm_new(struct snd_card *card, 349static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
326 struct snd_soc_dai *dai, struct snd_pcm *pcm)
327{ 350{
351 struct snd_card *card = rtd->card->snd_card;
352 struct snd_soc_dai *dai = rtd->cpu_dai;
353 struct snd_pcm *pcm = rtd->pcm;
328 int ret = 0; 354 int ret = 0;
329 355
330 if (!card->dev->dma_mask) 356 if (!card->dev->dma_mask)
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
new file mode 100644
index 00000000000..f6f4ed3d421
--- /dev/null
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -0,0 +1,738 @@
1/*
2 * tegra_rt5640.c - Tegra machine ASoC driver for boards using ALC5640 codec.
3 *
4 * Author: Johnny Qiu <joqiu@nvidia.com>
5 * Copyright (C) 2011-2012, NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright 2007 Wolfson Microelectronics PLC.
10 * Author: Graeme Gregory
11 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * version 2 as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 *
27 */
28
29#include <asm/mach-types.h>
30
31#include <linux/module.h>
32#include <linux/platform_device.h>
33#include <linux/slab.h>
34#include <linux/gpio.h>
35#include <linux/regulator/consumer.h>
36#ifdef CONFIG_SWITCH
37#include <linux/switch.h>
38#endif
39
40#include <mach/tegra_rt5640_pdata.h>
41
42#include <sound/core.h>
43#include <sound/jack.h>
44#include <sound/pcm.h>
45#include <sound/pcm_params.h>
46#include <sound/soc.h>
47
48#include "../codecs/rt5639.h"
49#include "../codecs/rt5640.h"
50
51#include "tegra_pcm.h"
52#include "tegra_asoc_utils.h"
53
54#define DRV_NAME "tegra-snd-rt5640"
55
56#define GPIO_SPKR_EN BIT(0)
57#define GPIO_HP_MUTE BIT(1)
58#define GPIO_INT_MIC_EN BIT(2)
59#define GPIO_EXT_MIC_EN BIT(3)
60#define GPIO_HP_DET BIT(4)
61
62struct tegra_rt5640 {
63 struct tegra_asoc_utils_data util_data;
64 struct tegra_rt5640_platform_data *pdata;
65 struct regulator *spk_reg;
66 struct regulator *dmic_reg;
67 struct regulator *cdc_en;
68 int gpio_requested;
69#ifdef CONFIG_SWITCH
70 int jack_status;
71#endif
72};
73
74static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
75 struct snd_pcm_hw_params *params)
76{
77 struct snd_soc_pcm_runtime *rtd = substream->private_data;
78 struct snd_soc_dai *codec_dai = rtd->codec_dai;
79 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
80 struct snd_soc_codec *codec = rtd->codec;
81 struct snd_soc_card *card = codec->card;
82 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
83 int srate, mclk, i2s_daifmt;
84 int err;
85
86 srate = params_rate(params);
87 mclk = 256 * srate;
88 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
89 if (err < 0) {
90 if (!(machine->util_data.set_mclk % mclk)) {
91 mclk = machine->util_data.set_mclk;
92 } else {
93 dev_err(card->dev, "Can't configure clocks\n");
94 return err;
95 }
96 }
97
98 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
99
100 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
101 SND_SOC_DAIFMT_CBS_CFS;
102
103 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
104
105 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
106 if (err < 0) {
107 dev_err(card->dev, "codec_dai fmt not set\n");
108 return err;
109 }
110
111 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
112 if (err < 0) {
113 dev_err(card->dev, "cpu_dai fmt not set\n");
114 return err;
115 }
116
117 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
118 SND_SOC_CLOCK_IN);
119 if (err < 0) {
120 dev_err(card->dev, "codec_dai clock not set\n");
121 return err;
122 }
123
124 return 0;
125}
126
127static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
128 struct snd_pcm_hw_params *params)
129{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
132 struct snd_soc_card *card = rtd->card;
133 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
134 int srate, mclk, min_mclk;
135 int err;
136
137 srate = params_rate(params);
138 switch (srate) {
139 case 11025:
140 case 22050:
141 case 44100:
142 case 88200:
143 mclk = 11289600;
144 break;
145 case 8000:
146 case 16000:
147 case 32000:
148 case 48000:
149 case 64000:
150 case 96000:
151 mclk = 12288000;
152 break;
153 default:
154 return -EINVAL;
155 }
156 min_mclk = 64 * srate;
157
158 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
159 if (err < 0) {
160 if (!(machine->util_data.set_mclk % min_mclk))
161 mclk = machine->util_data.set_mclk;
162 else {
163 dev_err(card->dev, "Can't configure clocks\n");
164 return err;
165 }
166 }
167
168 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
169
170 err = snd_soc_dai_set_fmt(cpu_dai,
171 SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF |
173 SND_SOC_DAIFMT_CBS_CFS);
174 if (err < 0) {
175 dev_err(card->dev, "cpu_dai fmt not set\n");
176 return err;
177 }
178
179 return 0;
180}
181
182static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params)
184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_card *card = rtd->card;
187 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
188 int srate, mclk, min_mclk;
189 int err;
190
191 srate = params_rate(params);
192 switch (srate) {
193 case 11025:
194 case 22050:
195 case 44100:
196 case 88200:
197 mclk = 11289600;
198 break;
199 case 8000:
200 case 16000:
201 case 32000:
202 case 48000:
203 case 64000:
204 case 96000:
205 mclk = 12288000;
206 break;
207 default:
208 return -EINVAL;
209 }
210 min_mclk = 128 * srate;
211
212 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
213 if (err < 0) {
214 if (!(machine->util_data.set_mclk % min_mclk))
215 mclk = machine->util_data.set_mclk;
216 else {
217 dev_err(card->dev, "Can't configure clocks\n");
218 return err;
219 }
220 }
221
222 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
223
224 return 0;
225}
226
227static int tegra_hw_free(struct snd_pcm_substream *substream)
228{
229 struct snd_soc_pcm_runtime *rtd = substream->private_data;
230 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
231
232 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
233
234 return 0;
235}
236
237static struct snd_soc_ops tegra_rt5640_ops = {
238 .hw_params = tegra_rt5640_hw_params,
239 .hw_free = tegra_hw_free,
240};
241
242static struct snd_soc_ops tegra_rt5640_bt_sco_ops = {
243 .hw_params = tegra_bt_sco_hw_params,
244 .hw_free = tegra_hw_free,
245};
246
247static struct snd_soc_ops tegra_spdif_ops = {
248 .hw_params = tegra_spdif_hw_params,
249 .hw_free = tegra_hw_free,
250};
251
252static struct snd_soc_jack tegra_rt5640_hp_jack;
253
254static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = {
255 .name = "headphone detect",
256 .report = SND_JACK_HEADPHONE,
257 .debounce_time = 150,
258 .invert = 1,
259};
260
261#ifdef CONFIG_SWITCH
262/* These values are copied from Android WiredAccessoryObserver */
263enum headset_state {
264 BIT_NO_HEADSET = 0,
265 BIT_HEADSET = (1 << 0),
266 BIT_HEADSET_NO_MIC = (1 << 1),
267};
268
269static struct switch_dev tegra_rt5640_headset_switch = {
270 .name = "h2w",
271};
272
273static int tegra_rt5640_jack_notifier(struct notifier_block *self,
274 unsigned long action, void *dev)
275{
276 struct snd_soc_jack *jack = dev;
277 struct snd_soc_codec *codec = jack->codec;
278 struct snd_soc_card *card = codec->card;
279 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
280 enum headset_state state = BIT_NO_HEADSET;
281 unsigned char status_jack;
282
283 if (jack == &tegra_rt5640_hp_jack) {
284 if (action) {
285 if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
286 status_jack = rt5639_headset_detect(codec, 1);
287 else if (!strncmp(machine->pdata->codec_name, "rt5640",
288 6))
289 status_jack = rt5640_headset_detect(codec, 1);
290
291 machine->jack_status &= ~SND_JACK_HEADPHONE;
292 machine->jack_status &= ~SND_JACK_MICROPHONE;
293 if (status_jack == RT5639_HEADPHO_DET ||
294 status_jack == RT5640_HEADPHO_DET)
295 machine->jack_status |=
296 SND_JACK_HEADPHONE;
297 else if (status_jack == RT5639_HEADSET_DET ||
298 status_jack == RT5640_HEADSET_DET) {
299 machine->jack_status |=
300 SND_JACK_HEADPHONE;
301 machine->jack_status |=
302 SND_JACK_MICROPHONE;
303 }
304 } else {
305 if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
306 rt5639_headset_detect(codec, 0);
307 else if (!strncmp(machine->pdata->codec_name, "rt5640",
308 6))
309 rt5640_headset_detect(codec, 0);
310
311 machine->jack_status &= ~SND_JACK_HEADPHONE;
312 machine->jack_status &= ~SND_JACK_MICROPHONE;
313 }
314 }
315
316 switch (machine->jack_status) {
317 case SND_JACK_HEADPHONE:
318 state = BIT_HEADSET_NO_MIC;
319 break;
320 case SND_JACK_HEADSET:
321 state = BIT_HEADSET;
322 break;
323 case SND_JACK_MICROPHONE:
324 /* mic: would not report */
325 default:
326 state = BIT_NO_HEADSET;
327 }
328
329 switch_set_state(&tegra_rt5640_headset_switch, state);
330
331 return NOTIFY_OK;
332}
333
334static struct notifier_block tegra_rt5640_jack_detect_nb = {
335 .notifier_call = tegra_rt5640_jack_notifier,
336};
337#else
338static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
339 {
340 .pin = "Headphone Jack",
341 .mask = SND_JACK_HEADPHONE,
342 },
343};
344
345#endif
346
347static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
348 struct snd_kcontrol *k, int event)
349{
350 struct snd_soc_dapm_context *dapm = w->dapm;
351 struct snd_soc_card *card = dapm->card;
352 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
353 struct tegra_rt5640_platform_data *pdata = machine->pdata;
354
355 if (machine->spk_reg) {
356 if (SND_SOC_DAPM_EVENT_ON(event))
357 regulator_enable(machine->spk_reg);
358 else
359 regulator_disable(machine->spk_reg);
360 }
361
362 if (!(machine->gpio_requested & GPIO_SPKR_EN))
363 return 0;
364
365 gpio_set_value_cansleep(pdata->gpio_spkr_en,
366 SND_SOC_DAPM_EVENT_ON(event));
367
368 return 0;
369}
370
371static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
372 struct snd_kcontrol *k, int event)
373{
374 struct snd_soc_dapm_context *dapm = w->dapm;
375 struct snd_soc_card *card = dapm->card;
376 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
377 struct tegra_rt5640_platform_data *pdata = machine->pdata;
378
379 if (!(machine->gpio_requested & GPIO_HP_MUTE))
380 return 0;
381
382 gpio_set_value_cansleep(pdata->gpio_hp_mute,
383 !SND_SOC_DAPM_EVENT_ON(event));
384
385 return 0;
386}
387
388static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
389 struct snd_kcontrol *k, int event)
390{
391 struct snd_soc_dapm_context *dapm = w->dapm;
392 struct snd_soc_card *card = dapm->card;
393 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
394 struct tegra_rt5640_platform_data *pdata = machine->pdata;
395
396 if (machine->dmic_reg) {
397 if (SND_SOC_DAPM_EVENT_ON(event))
398 regulator_enable(machine->dmic_reg);
399 else
400 regulator_disable(machine->dmic_reg);
401 }
402
403 if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
404 return 0;
405
406 gpio_set_value_cansleep(pdata->gpio_int_mic_en,
407 SND_SOC_DAPM_EVENT_ON(event));
408
409 return 0;
410}
411
412static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
413 struct snd_kcontrol *k, int event)
414{
415 struct snd_soc_dapm_context *dapm = w->dapm;
416 struct snd_soc_card *card = dapm->card;
417 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
418 struct tegra_rt5640_platform_data *pdata = machine->pdata;
419
420 if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
421 return 0;
422
423 gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
424 !SND_SOC_DAPM_EVENT_ON(event));
425
426 return 0;
427}
428
429static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
430 SND_SOC_DAPM_SPK("Int Spk", tegra_rt5640_event_int_spk),
431 SND_SOC_DAPM_HP("Headphone Jack", tegra_rt5640_event_hp),
432 SND_SOC_DAPM_MIC("Mic Jack", tegra_rt5640_event_ext_mic),
433 SND_SOC_DAPM_MIC("Int Mic", tegra_rt5640_event_int_mic),
434};
435
436static const struct snd_soc_dapm_route cardhu_audio_map[] = {
437 {"Headphone Jack", NULL, "HPOR"},
438 {"Headphone Jack", NULL, "HPOL"},
439 {"Int Spk", NULL, "SPORP"},
440 {"Int Spk", NULL, "SPORN"},
441 {"Int Spk", NULL, "SPOLP"},
442 {"Int Spk", NULL, "SPOLN"},
443 {"micbias1", NULL, "Mic Jack"},
444 {"IN1P", NULL, "micbias1"},
445 {"IN1N", NULL, "micbias1"},
446 {"micbias1", NULL, "Int Mic"},
447 {"IN2P", NULL, "micbias1"},
448};
449
450static const struct snd_kcontrol_new cardhu_controls[] = {
451 SOC_DAPM_PIN_SWITCH("Int Spk"),
452 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
453 SOC_DAPM_PIN_SWITCH("Mic Jack"),
454 SOC_DAPM_PIN_SWITCH("Int Mic"),
455};
456
457static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
458{
459 struct snd_soc_codec *codec = rtd->codec;
460 struct snd_soc_dapm_context *dapm = &codec->dapm;
461 struct snd_soc_card *card = codec->card;
462 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
463 struct tegra_rt5640_platform_data *pdata = machine->pdata;
464 int ret;
465
466 if (gpio_is_valid(pdata->gpio_spkr_en)) {
467 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
468 if (ret) {
469 dev_err(card->dev, "cannot get spkr_en gpio\n");
470 return ret;
471 }
472 machine->gpio_requested |= GPIO_SPKR_EN;
473
474 gpio_direction_output(pdata->gpio_spkr_en, 0);
475 }
476
477 if (gpio_is_valid(pdata->gpio_hp_mute)) {
478 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
479 if (ret) {
480 dev_err(card->dev, "cannot get hp_mute gpio\n");
481 return ret;
482 }
483 machine->gpio_requested |= GPIO_HP_MUTE;
484
485 gpio_direction_output(pdata->gpio_hp_mute, 0);
486 }
487
488 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
489 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
490 if (ret) {
491 dev_err(card->dev, "cannot get int_mic_en gpio\n");
492 return ret;
493 }
494 machine->gpio_requested |= GPIO_INT_MIC_EN;
495
496 /* Disable int mic; enable signal is active-high */
497 gpio_direction_output(pdata->gpio_int_mic_en, 0);
498 }
499
500 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
501 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
502 if (ret) {
503 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
504 return ret;
505 }
506 machine->gpio_requested |= GPIO_EXT_MIC_EN;
507
508 /* Enable ext mic; enable signal is active-low */
509 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
510 }
511
512 if (gpio_is_valid(pdata->gpio_hp_det)) {
513 tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
514 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
515 &tegra_rt5640_hp_jack);
516#ifndef CONFIG_SWITCH
517 snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
518 ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
519 tegra_rt5640_hp_jack_pins);
520#else
521 snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
522 &tegra_rt5640_jack_detect_nb);
523#endif
524 snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
525 1,
526 &tegra_rt5640_hp_jack_gpio);
527 machine->gpio_requested |= GPIO_HP_DET;
528 }
529
530 ret = snd_soc_add_controls(codec, cardhu_controls,
531 ARRAY_SIZE(cardhu_controls));
532 if (ret < 0)
533 return ret;
534
535 snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets,
536 ARRAY_SIZE(cardhu_dapm_widgets));
537
538 snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
539 ARRAY_SIZE(cardhu_audio_map));
540 /* FIXME: Calculate automatically based on DAPM routes? */
541 snd_soc_dapm_nc_pin(dapm, "LOUTL");
542 snd_soc_dapm_nc_pin(dapm, "LOUTR");
543
544 snd_soc_dapm_sync(dapm);
545
546 return 0;
547}
548
549static struct snd_soc_dai_link tegra_rt5640_dai[] = {
550 {
551 .name = "RT5640",
552 .stream_name = "RT5640 PCM",
553 .codec_name = "rt5640.4-001c",
554 .platform_name = "tegra-pcm-audio",
555 .cpu_dai_name = "tegra30-i2s.1",
556 .codec_dai_name = "rt5640-aif1",
557 .init = tegra_rt5640_init,
558 .ops = &tegra_rt5640_ops,
559 },
560 {
561 .name = "SPDIF",
562 .stream_name = "SPDIF PCM",
563 .codec_name = "spdif-dit.0",
564 .platform_name = "tegra-pcm-audio",
565 .cpu_dai_name = "tegra30-spdif",
566 .codec_dai_name = "dit-hifi",
567 .ops = &tegra_spdif_ops,
568 },
569 {
570 .name = "BT-SCO",
571 .stream_name = "BT SCO PCM",
572 .codec_name = "spdif-dit.1",
573 .platform_name = "tegra-pcm-audio",
574 .cpu_dai_name = "tegra30-i2s.3",
575 .codec_dai_name = "dit-hifi",
576 .ops = &tegra_rt5640_bt_sco_ops,
577 },
578};
579
580static struct snd_soc_card snd_soc_tegra_rt5640 = {
581 .name = "tegra-rt5640",
582 .dai_link = tegra_rt5640_dai,
583 .num_links = ARRAY_SIZE(tegra_rt5640_dai),
584};
585
586static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
587{
588 struct snd_soc_card *card = &snd_soc_tegra_rt5640;
589 struct tegra_rt5640 *machine;
590 struct tegra_rt5640_platform_data *pdata;
591 int ret;
592
593 pdata = pdev->dev.platform_data;
594 if (!pdata) {
595 dev_err(&pdev->dev, "No platform data supplied\n");
596 return -EINVAL;
597 }
598
599 if (pdata->codec_name)
600 card->dai_link->codec_name = pdata->codec_name;
601 if (pdata->codec_dai_name)
602 card->dai_link->codec_dai_name = pdata->codec_dai_name;
603
604 machine = kzalloc(sizeof(struct tegra_rt5640), GFP_KERNEL);
605 if (!machine) {
606 dev_err(&pdev->dev, "Can't allocate tegra_rt5640 struct\n");
607 return -ENOMEM;
608 }
609
610 machine->pdata = pdata;
611
612 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
613 if (ret)
614 goto err_free_machine;
615
616 machine->cdc_en = regulator_get(NULL, "cdc_en");
617 if (WARN_ON(IS_ERR(machine->cdc_en))) {
618 dev_err(&pdev->dev, "Couldn't get regulator cdc_en: %ld\n",
619 PTR_ERR(machine->cdc_en));
620 machine->cdc_en = 0;
621 } else {
622 regulator_enable(machine->cdc_en);
623 }
624
625 machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
626 if (IS_ERR(machine->spk_reg)) {
627 dev_info(&pdev->dev, "No speaker regulator found\n");
628 machine->spk_reg = 0;
629 }
630
631#ifdef CONFIG_SWITCH
632 /* Addd h2w swith class support */
633 ret = switch_dev_register(&tegra_rt5640_headset_switch);
634 if (ret < 0)
635 goto err_fini_utils;
636#endif
637
638 card->dev = &pdev->dev;
639 platform_set_drvdata(pdev, card);
640 snd_soc_card_set_drvdata(card, machine);
641
642 ret = snd_soc_register_card(card);
643 if (ret) {
644 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
645 ret);
646 goto err_unregister_switch;
647 }
648
649 if (!card->instantiated) {
650 ret = -ENODEV;
651 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
652 ret);
653 goto err_unregister_card;
654 }
655
656 return 0;
657
658err_unregister_card:
659 snd_soc_unregister_card(card);
660err_unregister_switch:
661#ifdef CONFIG_SWITCH
662 switch_dev_unregister(&tegra_rt5640_headset_switch);
663err_fini_utils:
664#endif
665 tegra_asoc_utils_fini(&machine->util_data);
666err_free_machine:
667 kfree(machine);
668 return ret;
669}
670
671static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
672{
673 struct snd_soc_card *card = platform_get_drvdata(pdev);
674 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
675 struct tegra_rt5640_platform_data *pdata = machine->pdata;
676
677 if (machine->gpio_requested & GPIO_HP_DET)
678 snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
679 1,
680 &tegra_rt5640_hp_jack_gpio);
681 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
682 gpio_free(pdata->gpio_ext_mic_en);
683 if (machine->gpio_requested & GPIO_INT_MIC_EN)
684 gpio_free(pdata->gpio_int_mic_en);
685 if (machine->gpio_requested & GPIO_HP_MUTE)
686 gpio_free(pdata->gpio_hp_mute);
687 if (machine->gpio_requested & GPIO_SPKR_EN)
688 gpio_free(pdata->gpio_spkr_en);
689 machine->gpio_requested = 0;
690
691 if (machine->spk_reg)
692 regulator_put(machine->spk_reg);
693 if (machine->dmic_reg)
694 regulator_put(machine->dmic_reg);
695
696 if (machine->cdc_en) {
697 regulator_disable(machine->cdc_en);
698 regulator_put(machine->cdc_en);
699 }
700
701 snd_soc_unregister_card(card);
702
703 tegra_asoc_utils_fini(&machine->util_data);
704
705#ifdef CONFIG_SWITCH
706 switch_dev_unregister(&tegra_rt5640_headset_switch);
707#endif
708 kfree(machine);
709
710 return 0;
711}
712
713static struct platform_driver tegra_rt5640_driver = {
714 .driver = {
715 .name = DRV_NAME,
716 .owner = THIS_MODULE,
717 .pm = &snd_soc_pm_ops,
718 },
719 .probe = tegra_rt5640_driver_probe,
720 .remove = __devexit_p(tegra_rt5640_driver_remove),
721};
722
723static int __init tegra_rt5640_modinit(void)
724{
725 return platform_driver_register(&tegra_rt5640_driver);
726}
727module_init(tegra_rt5640_modinit);
728
729static void __exit tegra_rt5640_modexit(void)
730{
731 platform_driver_unregister(&tegra_rt5640_driver);
732}
733module_exit(tegra_rt5640_modexit);
734
735MODULE_AUTHOR("Johnny Qiu <joqiu@nvidia.com>");
736MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver");
737MODULE_LICENSE("GPL");
738MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
new file mode 100644
index 00000000000..62c1c056a61
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -0,0 +1,972 @@
1/*
2 * tegra_wm8753.c - Tegra machine ASoC driver for boards using WM8753 codec.
3 *
4 * Author: Sumit Bhattacharya <sumitb@nvidia.com>
5 * Copyright (C) 2010-2011 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10 *
11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <asm/mach-types.h>
32
33#include <linux/module.h>
34#include <linux/platform_device.h>
35#include <linux/slab.h>
36#include <linux/gpio.h>
37#include <linux/regulator/consumer.h>
38#ifdef CONFIG_SWITCH
39#include <linux/switch.h>
40#endif
41
42#include <mach/tegra_wm8753_pdata.h>
43
44#include <sound/core.h>
45#include <sound/jack.h>
46#include <sound/pcm.h>
47#include <sound/pcm_params.h>
48#include <sound/soc.h>
49
50#include "../codecs/wm8753.h"
51
52#include "tegra_pcm.h"
53#include "tegra_asoc_utils.h"
54
55#ifdef CONFIG_ARCH_TEGRA_2x_SOC
56#include "tegra20_das.h"
57#endif
58
59#define DRV_NAME "tegra-snd-wm8753"
60
61#define GPIO_SPKR_EN BIT(0)
62#define GPIO_HP_MUTE BIT(1)
63#define GPIO_INT_MIC_EN BIT(2)
64#define GPIO_EXT_MIC_EN BIT(3)
65
66extern int g_is_call_mode;
67
68struct tegra_wm8753 {
69 struct tegra_asoc_utils_data util_data;
70 struct tegra_wm8753_platform_data *pdata;
71 struct regulator *audio_reg;
72 int gpio_requested;
73 int is_call_mode;
74 int is_call_mode_bt;
75};
76
77static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params)
79{
80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
83 struct snd_soc_codec *codec = rtd->codec;
84 struct snd_soc_card *card = codec->card;
85 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
86 int srate, mclk, i2s_daifmt;
87 int err;
88 srate = params_rate(params);
89 switch (srate) {
90 case 8000:
91 case 16000:
92 case 24000:
93 case 32000:
94 case 48000:
95 case 64000:
96 case 96000:
97 mclk = 12288000;
98 break;
99 case 11025:
100 case 22050:
101 case 44100:
102 case 88200:
103 mclk = 11289600;
104 break;
105 default:
106 mclk = 12000000;
107 break;
108 }
109
110 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
111 if (err < 0) {
112 if (!(machine->util_data.set_mclk % mclk))
113 mclk = machine->util_data.set_mclk;
114 else {
115 dev_err(card->dev, "Can't configure clocks\n");
116 return err;
117 }
118 }
119
120 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
121
122 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
123 SND_SOC_DAIFMT_CBS_CFS;
124
125 /* Use DSP mode for mono on Tegra20 */
126 if ((params_channels(params) != 2) && machine_is_whistler())
127 i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
128 else
129 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
130
131 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
132 if (err < 0) {
133 dev_err(card->dev, "codec_dai fmt not set\n");
134 return err;
135 }
136
137 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
138 if (err < 0) {
139 dev_err(card->dev, "cpu_dai fmt not set\n");
140 return err;
141 }
142
143 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
144 SND_SOC_CLOCK_IN);
145 if (err < 0) {
146 dev_err(card->dev, "codec_dai clock not set\n");
147 return err;
148 }
149
150#ifdef CONFIG_ARCH_TEGRA_2x_SOC
151 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
152 TEGRA20_DAS_DAP_ID_1);
153 if (err < 0) {
154 dev_err(card->dev, "failed to set dap-dac path\n");
155 return err;
156 }
157
158 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
159 TEGRA20_DAS_DAP_SEL_DAC1);
160 if (err < 0) {
161 dev_err(card->dev, "failed to set dac-dap path\n");
162 return err;
163 }
164#endif
165 return 0;
166}
167
168static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
169 struct snd_pcm_hw_params *params)
170{
171 struct snd_soc_pcm_runtime *rtd = substream->private_data;
172 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
173 struct snd_soc_codec *codec = rtd->codec;
174 struct snd_soc_card *card = codec->card;
175 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
176 int srate, mclk, min_mclk;
177 int err;
178
179 srate = params_rate(params);
180 switch (srate) {
181 case 11025:
182 case 22050:
183 case 44100:
184 case 88200:
185 mclk = 11289600;
186 break;
187 case 8000:
188 case 16000:
189 case 32000:
190 case 48000:
191 case 64000:
192 case 96000:
193 mclk = 12288000;
194 break;
195 default:
196 return -EINVAL;
197 }
198 min_mclk = 64 * srate;
199
200 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
201 if (err < 0) {
202 if (!(machine->util_data.set_mclk % min_mclk))
203 mclk = machine->util_data.set_mclk;
204 else {
205 dev_err(card->dev, "Can't configure clocks\n");
206 return err;
207 }
208 }
209
210 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
211
212 err = snd_soc_dai_set_fmt(cpu_dai,
213 SND_SOC_DAIFMT_DSP_A |
214 SND_SOC_DAIFMT_NB_NF |
215 SND_SOC_DAIFMT_CBS_CFS);
216 if (err < 0) {
217 dev_err(card->dev, "cpu_dai fmt not set\n");
218 return err;
219 }
220
221#ifdef CONFIG_ARCH_TEGRA_2x_SOC
222 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
223 TEGRA20_DAS_DAP_ID_4);
224 if (err < 0) {
225 dev_err(card->dev, "failed to set dac-dap path\n");
226 return err;
227 }
228
229 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
230 TEGRA20_DAS_DAP_SEL_DAC2);
231 if (err < 0) {
232 dev_err(card->dev, "failed to set dac-dap path\n");
233 return err;
234 }
235#endif
236 return 0;
237}
238
239static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
240 struct snd_pcm_hw_params *params)
241{
242 struct snd_soc_pcm_runtime *rtd = substream->private_data;
243 struct snd_soc_card *card = rtd->card;
244 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
245 int srate, mclk, min_mclk;
246 int err;
247
248 srate = params_rate(params);
249 switch (srate) {
250 case 11025:
251 case 22050:
252 case 44100:
253 case 88200:
254 mclk = 11289600;
255 break;
256 case 8000:
257 case 16000:
258 case 32000:
259 case 48000:
260 case 64000:
261 case 96000:
262 mclk = 12288000;
263 break;
264 default:
265 return -EINVAL;
266 }
267 min_mclk = 128 * srate;
268
269 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
270 if (err < 0) {
271 if (!(machine->util_data.set_mclk % min_mclk))
272 mclk = machine->util_data.set_mclk;
273 else {
274 dev_err(card->dev, "Can't configure clocks\n");
275 return err;
276 }
277 }
278
279 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
280
281 return 0;
282}
283
284static int tegra_wm8753_voice_hw_params(struct snd_pcm_substream *substream,
285 struct snd_pcm_hw_params *params)
286{
287 struct snd_soc_pcm_runtime *rtd = substream->private_data;
288 struct snd_soc_dai *codec_dai = rtd->codec_dai;
289 struct snd_soc_codec *codec = rtd->codec;
290 struct snd_soc_card *card = codec->card;
291 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
292 int srate, mclk, i2s_daifmt, sys_clk;
293 int err, pcmdiv, vxclkdiv;
294
295 srate = params_rate(params);
296 switch (srate) {
297 case 8000:
298 case 16000:
299 case 24000:
300 case 32000:
301 case 48000:
302 case 64000:
303 case 96000:
304 mclk = 12288000;
305 break;
306 case 11025:
307 case 22050:
308 case 44100:
309 case 88200:
310 mclk = 11289600;
311 break;
312 default:
313 mclk = 12000000;
314 break;
315 }
316
317 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
318 if (err < 0) {
319 if (!(machine->util_data.set_mclk % mclk))
320 mclk = machine->util_data.set_mclk;
321 else {
322 dev_err(card->dev, "Can't configure clocks\n");
323 return err;
324 }
325 }
326
327 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
328
329 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
330 SND_SOC_DAIFMT_CBM_CFM;
331
332 i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
333
334 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
335 if (err < 0) {
336 dev_err(card->dev, "codec_dai fmt not set\n");
337 return err;
338 }
339
340 sys_clk = machine->util_data.set_mclk;
341
342 err = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, sys_clk,
343 SND_SOC_CLOCK_IN);
344 if (err < 0) {
345 dev_err(card->dev, "codec_dai clock not set\n");
346 return err;
347 }
348
349 err = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
350 sys_clk, 12288000);
351
352 if (err < 0) {
353 dev_err(card->dev, "codec_dai pll not set\n");
354 return err;
355 }
356
357 if (params_rate(params) == 8000) {
358 pcmdiv = WM8753_PCM_DIV_6;
359 /* BB expecting 2048Khz bclk */
360 vxclkdiv = WM8753_VXCLK_DIV_1;
361 } else if (params_rate(params) == 16000) {
362 pcmdiv = WM8753_PCM_DIV_3;
363 /* BB expecting 2048Khz bclk */
364 vxclkdiv = WM8753_VXCLK_DIV_2;
365 } else {
366 dev_err(card->dev, "codec_dai unsupported voice rate\n");
367 return -EINVAL;
368 }
369
370 snd_soc_dai_set_clkdiv(codec_dai, WM8753_VXCLKDIV, vxclkdiv);
371 snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
372
373 machine->is_call_mode_bt = 0;
374
375 return 0;
376}
377
378static int tegra_bt_call_hw_params(struct snd_pcm_substream *substream,
379 struct snd_pcm_hw_params *params)
380{
381 struct snd_soc_pcm_runtime *rtd = substream->private_data;
382 struct snd_soc_dai *codec_dai = rtd->codec_dai;
383 struct snd_soc_codec *codec = rtd->codec;
384 struct snd_soc_card *card = codec->card;
385 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
386 int srate, mclk;
387 int err;
388
389 srate = params_rate(params);
390 switch (srate) {
391 case 8000:
392 case 16000:
393 case 24000:
394 case 32000:
395 case 48000:
396 case 64000:
397 case 96000:
398 mclk = 12288000;
399 break;
400 case 11025:
401 case 22050:
402 case 44100:
403 case 88200:
404 mclk = 11289600;
405 break;
406 default:
407 mclk = 12000000;
408 break;
409 }
410
411 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
412 if (err < 0) {
413 if (!(machine->util_data.set_mclk % mclk))
414 mclk = machine->util_data.set_mclk;
415 else {
416 dev_err(card->dev, "Can't configure clocks\n");
417 return err;
418 }
419 }
420
421 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
422
423 machine->is_call_mode_bt = 1;
424
425 return 0;
426}
427
428
429static int tegra_hw_free(struct snd_pcm_substream *substream)
430{
431 struct snd_soc_pcm_runtime *rtd = substream->private_data;
432 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(rtd->card);
433
434 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
435
436 return 0;
437}
438
439static int tegra_bt_call_hw_free(struct snd_pcm_substream *substream)
440{
441 struct snd_soc_pcm_runtime *rtd = substream->private_data;
442 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(rtd->card);
443
444 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
445 machine->is_call_mode_bt = 0;
446
447 return 0;
448}
449
450static int tegra_wm8753_voice_hw_free(struct snd_pcm_substream *substream)
451{
452 struct snd_soc_pcm_runtime *rtd = substream->private_data;
453 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(rtd->card);
454
455 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
456 machine->is_call_mode_bt = 0;
457
458 return 0;
459}
460
461static int tegra_call_mode_info(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_info *uinfo)
463{
464 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
465 uinfo->count = 1;
466 uinfo->value.integer.min = 0;
467 uinfo->value.integer.max = 1;
468 return 0;
469}
470
471static int tegra_call_mode_get(struct snd_kcontrol *kcontrol,
472 struct snd_ctl_elem_value *ucontrol)
473{
474 struct tegra_wm8753 *machine = snd_kcontrol_chip(kcontrol);
475
476 ucontrol->value.integer.value[0] = machine->is_call_mode;
477
478 return 0;
479}
480
481static int tegra_call_mode_put(struct snd_kcontrol *kcontrol,
482 struct snd_ctl_elem_value *ucontrol)
483{
484 struct tegra_wm8753 *machine = snd_kcontrol_chip(kcontrol);
485 int is_call_mode_new = ucontrol->value.integer.value[0];
486 int codec_dap_id, codec_dap_sel, bb_dap_id, bb_dap_sel;
487
488 if (machine->is_call_mode == is_call_mode_new)
489 return 0;
490
491 bb_dap_id = TEGRA20_DAS_DAP_ID_3;
492 bb_dap_sel = TEGRA20_DAS_DAP_SEL_DAP3;
493
494 if (machine->is_call_mode_bt) {
495 codec_dap_id = TEGRA20_DAS_DAP_ID_4;
496 codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP4;
497 }
498 else {
499 codec_dap_id = TEGRA20_DAS_DAP_ID_2;
500 codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP2;
501 }
502
503 if (is_call_mode_new) {
504#ifdef CONFIG_ARCH_TEGRA_2x_SOC
505 tegra20_das_set_tristate(codec_dap_id, 1);
506 tegra20_das_set_tristate(bb_dap_id, 1);
507 tegra20_das_connect_dap_to_dap(codec_dap_id,
508 bb_dap_sel, 0, 0, 0);
509 tegra20_das_connect_dap_to_dap(bb_dap_id,
510 codec_dap_sel, 1, 0, 0);
511 tegra20_das_set_tristate(codec_dap_id, 0);
512 tegra20_das_set_tristate(bb_dap_id, 0);
513#endif
514 } else {
515#ifdef CONFIG_ARCH_TEGRA_2x_SOC
516 tegra20_das_set_tristate(codec_dap_id, 1);
517 tegra20_das_set_tristate(bb_dap_id, 1);
518 tegra20_das_connect_dap_to_dap(bb_dap_id,
519 bb_dap_sel, 0, 0, 0);
520 tegra20_das_connect_dap_to_dap(codec_dap_id,
521 codec_dap_sel, 0, 0, 0);
522 tegra20_das_set_tristate(codec_dap_id, 0);
523 tegra20_das_set_tristate(bb_dap_id, 0);
524#endif
525 }
526
527 machine->is_call_mode = is_call_mode_new;
528 g_is_call_mode = machine->is_call_mode;
529
530 return 1;
531}
532
533struct snd_kcontrol_new tegra_call_mode_control = {
534 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
535 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
536 .name = "Call Mode Switch",
537 .private_value = 0xffff,
538 .info = tegra_call_mode_info,
539 .get = tegra_call_mode_get,
540 .put = tegra_call_mode_put
541};
542
543static struct snd_soc_ops tegra_wm8753_ops = {
544 .hw_params = tegra_wm8753_hw_params,
545 .hw_free = tegra_hw_free,
546};
547
548static struct snd_soc_ops tegra_wm8753_voice_ops = {
549 .hw_params = tegra_wm8753_voice_hw_params,
550 .hw_free = tegra_wm8753_voice_hw_free,
551};
552
553static struct snd_soc_ops tegra_bt_call_ops = {
554 .hw_params = tegra_bt_call_hw_params,
555 .hw_free = tegra_bt_call_hw_free,
556};
557
558static struct snd_soc_ops tegra_bt_sco_ops = {
559 .hw_params = tegra_bt_sco_hw_params,
560 .hw_free = tegra_hw_free,
561};
562
563static struct snd_soc_ops tegra_spdif_ops = {
564 .hw_params = tegra_spdif_hw_params,
565 .hw_free = tegra_hw_free,
566};
567
568static struct snd_soc_jack tegra_wm8753_hp_jack;
569
570#ifdef CONFIG_SWITCH
571static struct switch_dev wired_switch_dev = {
572 .name = "h2w",
573};
574
575/* These values are copied from WiredAccessoryObserver */
576enum headset_state {
577 BIT_NO_HEADSET = 0,
578 BIT_HEADSET = (1 << 0),
579 BIT_HEADSET_NO_MIC = (1 << 1),
580};
581
582static int headset_switch_notify(struct notifier_block *self,
583 unsigned long action, void *dev)
584{
585 switch (action) {
586 case SND_JACK_HEADPHONE:
587 switch_set_state(&wired_switch_dev, BIT_HEADSET_NO_MIC);
588 break;
589 case SND_JACK_HEADSET:
590 switch_set_state(&wired_switch_dev, BIT_HEADSET);
591 break;
592 default:
593 switch_set_state(&wired_switch_dev, BIT_NO_HEADSET);
594 }
595
596 return NOTIFY_OK;
597}
598
599static struct notifier_block headset_switch_nb = {
600 .notifier_call = headset_switch_notify,
601};
602#else
603static struct snd_soc_jack_pin tegra_wm8753_hp_jack_pins[] = {
604 {
605 .pin = "Headphone Jack",
606 .mask = SND_JACK_HEADPHONE,
607 },
608};
609#endif
610
611static int tegra_wm8753_event_int_spk(struct snd_soc_dapm_widget *w,
612 struct snd_kcontrol *k, int event)
613{
614 struct snd_soc_dapm_context *dapm = w->dapm;
615 struct snd_soc_card *card = dapm->card;
616 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
617 struct tegra_wm8753_platform_data *pdata = machine->pdata;
618
619 if (!(machine->gpio_requested & GPIO_SPKR_EN))
620 return 0;
621
622 gpio_set_value_cansleep(pdata->gpio_spkr_en,
623 SND_SOC_DAPM_EVENT_ON(event));
624
625 return 0;
626}
627
628static int tegra_wm8753_event_hp(struct snd_soc_dapm_widget *w,
629 struct snd_kcontrol *k, int event)
630{
631 struct snd_soc_dapm_context *dapm = w->dapm;
632 struct snd_soc_card *card = dapm->card;
633 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
634 struct tegra_wm8753_platform_data *pdata = machine->pdata;
635
636 if (!(machine->gpio_requested & GPIO_HP_MUTE))
637 return 0;
638
639 gpio_set_value_cansleep(pdata->gpio_hp_mute,
640 !SND_SOC_DAPM_EVENT_ON(event));
641
642 return 0;
643}
644
645static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = {
646 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8753_event_int_spk),
647 SND_SOC_DAPM_HP("Earpiece", NULL),
648 SND_SOC_DAPM_OUTPUT("Mono Out"),
649 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8753_event_hp),
650 SND_SOC_DAPM_MIC("Mic Jack", NULL),
651 SND_SOC_DAPM_INPUT("Int Mic"),
652 SND_SOC_DAPM_LINE("LineIn Jack", NULL),
653};
654
655static const struct snd_soc_dapm_route whistler_audio_map[] = {
656 {"Int Spk", NULL, "ROUT2"},
657 {"Int Spk", NULL, "LOUT2"},
658 {"Earpiece", NULL, "OUT3"},
659 {"Earpiece", NULL, "LOUT1"},
660 {"Mono Out", NULL, "MONO1"},
661 {"Mono Out", NULL, "MONO2"},
662 {"Headphone Jack", NULL, "ROUT1"},
663 {"Headphone Jack", NULL, "LOUT1"},
664 {"Headphone Jack", NULL, "OUT4"},
665 {"Mic Bias", NULL, "Mic Jack"},
666 {"MIC1", NULL, "Mic Bias"},
667 {"Mic Bias", NULL, "Int Mic"},
668 {"MIC2", NULL, "Mic Bias"},
669 {"MIC2N", NULL, "Mic Bias"},
670 {"LINE1", NULL, "LineIn Jack"},
671 {"LINE2", NULL, "LineIn Jack"},
672};
673
674static const struct snd_kcontrol_new tegra_wm8753_controls[] = {
675 SOC_DAPM_PIN_SWITCH("Int Spk"),
676 SOC_DAPM_PIN_SWITCH("Earpiece"),
677 SOC_DAPM_PIN_SWITCH("Mono Out"),
678 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
679 SOC_DAPM_PIN_SWITCH("Mic Jack"),
680 SOC_DAPM_PIN_SWITCH("Int Mic"),
681 SOC_DAPM_PIN_SWITCH("LineIn Jack"),
682};
683
684static int tegra_wm8753_init(struct snd_soc_pcm_runtime *rtd)
685{
686 struct snd_soc_codec *codec = rtd->codec;
687 struct snd_soc_dapm_context *dapm = &codec->dapm;
688 struct snd_soc_card *card = codec->card;
689 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
690 struct tegra_wm8753_platform_data *pdata = machine->pdata;
691 int ret;
692
693 if (machine_is_whistler()) {
694 machine->audio_reg = regulator_get(NULL, "avddio_audio");
695 if (IS_ERR(machine->audio_reg)) {
696 dev_err(card->dev, "cannot get avddio_audio reg\n");
697 ret = PTR_ERR(machine->audio_reg);
698 return ret;
699 }
700
701 ret = regulator_enable(machine->audio_reg);
702 if (ret) {
703 dev_err(card->dev, "cannot enable avddio_audio reg\n");
704 regulator_put(machine->audio_reg);
705 machine->audio_reg = NULL;
706 return ret;
707 }
708 }
709
710 if (gpio_is_valid(pdata->gpio_spkr_en)) {
711 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
712 if (ret) {
713 dev_err(card->dev, "cannot get spkr_en gpio\n");
714 return ret;
715 }
716 machine->gpio_requested |= GPIO_SPKR_EN;
717
718 gpio_direction_output(pdata->gpio_spkr_en, 0);
719 }
720
721 if (gpio_is_valid(pdata->gpio_hp_mute)) {
722 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
723 if (ret) {
724 dev_err(card->dev, "cannot get hp_mute gpio\n");
725 return ret;
726 }
727 machine->gpio_requested |= GPIO_HP_MUTE;
728
729 gpio_direction_output(pdata->gpio_hp_mute, 0);
730 }
731
732 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
733 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
734 if (ret) {
735 dev_err(card->dev, "cannot get int_mic_en gpio\n");
736 return ret;
737 }
738 machine->gpio_requested |= GPIO_INT_MIC_EN;
739
740 /* Disable int mic; enable signal is active-high */
741 gpio_direction_output(pdata->gpio_int_mic_en, 0);
742 }
743
744 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
745 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
746 if (ret) {
747 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
748 return ret;
749 }
750 machine->gpio_requested |= GPIO_EXT_MIC_EN;
751
752 /* Enable ext mic; enable signal is active-low */
753 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
754 }
755
756 ret = snd_soc_add_controls(codec, tegra_wm8753_controls,
757 ARRAY_SIZE(tegra_wm8753_controls));
758 if (ret < 0)
759 return ret;
760
761 snd_soc_dapm_new_controls(dapm, tegra_wm8753_dapm_widgets,
762 ARRAY_SIZE(tegra_wm8753_dapm_widgets));
763
764 snd_soc_dapm_add_routes(dapm, whistler_audio_map,
765 ARRAY_SIZE(whistler_audio_map));
766
767 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
768 &tegra_wm8753_hp_jack);
769 wm8753_headphone_detect(codec, &tegra_wm8753_hp_jack,
770 SND_JACK_HEADPHONE, pdata->debounce_time_hp);
771#ifdef CONFIG_SWITCH
772 snd_soc_jack_notifier_register(&tegra_wm8753_hp_jack,
773 &headset_switch_nb);
774#else
775 snd_soc_jack_add_pins(&tegra_wm8753_hp_jack,
776 ARRAY_SIZE(tegra_wm8753_hp_jack_pins),
777 tegra_wm8753_hp_jack_pins);
778#endif
779
780 /* Add call mode switch control */
781 ret = snd_ctl_add(codec->card->snd_card,
782 snd_ctl_new1(&tegra_call_mode_control, machine));
783 if (ret < 0)
784 return ret;
785
786 snd_soc_dapm_nc_pin(dapm, "ACIN");
787 snd_soc_dapm_nc_pin(dapm, "ACOP");
788 snd_soc_dapm_nc_pin(dapm, "OUT3");
789 snd_soc_dapm_nc_pin(dapm, "OUT4");
790
791 snd_soc_dapm_sync(dapm);
792
793 return 0;
794}
795
796static struct snd_soc_dai_link tegra_wm8753_dai[] = {
797 {
798 .name = "WM8753",
799 .stream_name = "WM8753 PCM HIFI",
800 .codec_name = "wm8753-codec.4-001a",
801 .platform_name = "tegra-pcm-audio",
802 .cpu_dai_name = "tegra20-i2s.0",
803 .codec_dai_name = "wm8753-hifi",
804 .init = tegra_wm8753_init,
805 .ops = &tegra_wm8753_ops,
806 },
807 {
808 .name = "SPDIF",
809 .stream_name = "SPDIF PCM",
810 .codec_name = "spdif-dit.0",
811 .platform_name = "tegra-pcm-audio",
812 .cpu_dai_name = "tegra20-spdif",
813 .codec_dai_name = "dit-hifi",
814 .ops = &tegra_spdif_ops,
815 },
816#ifdef CONFIG_ARCH_TEGRA_2x_SOC
817 {
818 .name = "BT-SCO",
819 .stream_name = "BT SCO PCM",
820 .codec_name = "spdif-dit.1",
821 .platform_name = "tegra-pcm-audio",
822 .cpu_dai_name = "tegra20-i2s.1",
823 .codec_dai_name = "dit-hifi",
824 .ops = &tegra_bt_sco_ops,
825 },
826#endif
827 {
828 .name = "VOICE CALL",
829 .stream_name = "VOICE CALL PCM",
830 .codec_name = "wm8753-codec.4-001a",
831 .platform_name = "tegra-pcm-audio",
832 .cpu_dai_name = "dit-hifi",
833 .codec_dai_name = "wm8753-voice",
834 .ops = &tegra_wm8753_voice_ops,
835 },
836 {
837 .name = "BT VOICE CALL",
838 .stream_name = "BT VOICE CALL PCM",
839 .codec_name = "spdif-dit.2",
840 .platform_name = "tegra-pcm-audio",
841 .cpu_dai_name = "dit-hifi",
842 .codec_dai_name = "dit-hifi",
843 .ops = &tegra_bt_call_ops,
844 },
845};
846
847static struct snd_soc_card snd_soc_tegra_wm8753 = {
848 .name = "tegra-wm8753",
849 .dai_link = tegra_wm8753_dai,
850 .num_links = ARRAY_SIZE(tegra_wm8753_dai),
851};
852
853static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
854{
855 struct snd_soc_card *card = &snd_soc_tegra_wm8753;
856 struct tegra_wm8753 *machine;
857 struct tegra_wm8753_platform_data *pdata;
858 int ret;
859
860
861 pdata = pdev->dev.platform_data;
862 if (!pdata) {
863 dev_err(&pdev->dev, "No platform data supplied\n");
864 return -EINVAL;
865 }
866
867 machine = kzalloc(sizeof(struct tegra_wm8753), GFP_KERNEL);
868 if (!machine) {
869 dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
870 return -ENOMEM;
871 }
872
873 machine->pdata = pdata;
874
875 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
876 if (ret)
877 goto err_free_machine;
878
879 card->dev = &pdev->dev;
880 platform_set_drvdata(pdev, card);
881 snd_soc_card_set_drvdata(card, machine);
882
883 ret = snd_soc_register_card(card);
884 if (ret) {
885 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
886 ret);
887 goto err_fini_utils;
888 }
889
890 if (!card->instantiated) {
891 dev_err(&pdev->dev, "No WM8753 codec\n");
892 goto err_unregister_card;
893 }
894
895#ifdef CONFIG_SWITCH
896 /* Add h2w swith class support */
897 ret = switch_dev_register(&wired_switch_dev);
898 if (ret < 0) {
899 dev_err(&pdev->dev, "not able to register switch device\n");
900 goto err_unregister_card;
901 }
902#endif
903
904 return 0;
905
906err_unregister_card:
907 snd_soc_unregister_card(card);
908err_fini_utils:
909 tegra_asoc_utils_fini(&machine->util_data);
910err_free_machine:
911 kfree(machine);
912 return ret;
913}
914
915static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
916{
917 struct snd_soc_card *card = platform_get_drvdata(pdev);
918 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
919 struct tegra_wm8753_platform_data *pdata = machine->pdata;
920
921 snd_soc_unregister_card(card);
922
923#ifdef CONFIG_SWITCH
924 switch_dev_unregister(&wired_switch_dev);
925#endif
926
927 tegra_asoc_utils_fini(&machine->util_data);
928
929 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
930 gpio_free(pdata->gpio_ext_mic_en);
931 if (machine->gpio_requested & GPIO_INT_MIC_EN)
932 gpio_free(pdata->gpio_int_mic_en);
933 if (machine->gpio_requested & GPIO_HP_MUTE)
934 gpio_free(pdata->gpio_hp_mute);
935 if (machine->gpio_requested & GPIO_SPKR_EN)
936 gpio_free(pdata->gpio_spkr_en);
937 if (machine->audio_reg) {
938 regulator_disable(machine->audio_reg);
939 regulator_put(machine->audio_reg);
940 }
941
942 kfree(machine);
943
944 return 0;
945}
946
947static struct platform_driver tegra_wm8753_driver = {
948 .driver = {
949 .name = DRV_NAME,
950 .owner = THIS_MODULE,
951 .pm = &snd_soc_pm_ops,
952 },
953 .probe = tegra_wm8753_driver_probe,
954 .remove = __devexit_p(tegra_wm8753_driver_remove),
955};
956
957static int __init tegra_wm8753_modinit(void)
958{
959 return platform_driver_register(&tegra_wm8753_driver);
960}
961module_init(tegra_wm8753_modinit);
962
963static void __exit tegra_wm8753_modexit(void)
964{
965 platform_driver_unregister(&tegra_wm8753_driver);
966}
967module_exit(tegra_wm8753_modexit);
968
969MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
970MODULE_DESCRIPTION("Tegra+WM8753 machine ASoC driver");
971MODULE_LICENSE("GPL");
972MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 0d6738a8b29..55e4f61edfd 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -30,10 +30,15 @@
30 30
31#include <asm/mach-types.h> 31#include <asm/mach-types.h>
32 32
33#include <linux/clk.h>
33#include <linux/module.h> 34#include <linux/module.h>
34#include <linux/platform_device.h> 35#include <linux/platform_device.h>
35#include <linux/slab.h> 36#include <linux/slab.h>
36#include <linux/gpio.h> 37#include <linux/gpio.h>
38#include <linux/regulator/consumer.h>
39#ifdef CONFIG_SWITCH
40#include <linux/switch.h>
41#endif
37 42
38#include <mach/tegra_wm8903_pdata.h> 43#include <mach/tegra_wm8903_pdata.h>
39 44
@@ -45,22 +50,31 @@
45 50
46#include "../codecs/wm8903.h" 51#include "../codecs/wm8903.h"
47 52
48#include "tegra_das.h"
49#include "tegra_i2s.h"
50#include "tegra_pcm.h" 53#include "tegra_pcm.h"
51#include "tegra_asoc_utils.h" 54#include "tegra_asoc_utils.h"
52 55
56#ifdef CONFIG_ARCH_TEGRA_2x_SOC
57#include "tegra20_das.h"
58#endif
59
53#define DRV_NAME "tegra-snd-wm8903" 60#define DRV_NAME "tegra-snd-wm8903"
54 61
55#define GPIO_SPKR_EN BIT(0) 62#define GPIO_SPKR_EN BIT(0)
56#define GPIO_HP_MUTE BIT(1) 63#define GPIO_HP_MUTE BIT(1)
57#define GPIO_INT_MIC_EN BIT(2) 64#define GPIO_INT_MIC_EN BIT(2)
58#define GPIO_EXT_MIC_EN BIT(3) 65#define GPIO_EXT_MIC_EN BIT(3)
66#define GPIO_HP_DET BIT(4)
59 67
60struct tegra_wm8903 { 68struct tegra_wm8903 {
61 struct tegra_asoc_utils_data util_data; 69 struct tegra_asoc_utils_data util_data;
62 struct tegra_wm8903_platform_data *pdata; 70 struct tegra_wm8903_platform_data *pdata;
71 struct regulator *spk_reg;
72 struct regulator *dmic_reg;
63 int gpio_requested; 73 int gpio_requested;
74#ifdef CONFIG_SWITCH
75 int jack_status;
76#endif
77 enum snd_soc_bias_level bias_level;
64}; 78};
65 79
66static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, 80static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
@@ -72,8 +86,10 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
72 struct snd_soc_codec *codec = rtd->codec; 86 struct snd_soc_codec *codec = rtd->codec;
73 struct snd_soc_card *card = codec->card; 87 struct snd_soc_card *card = codec->card;
74 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 88 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
75 int srate, mclk; 89 int srate, mclk, i2s_daifmt;
76 int err; 90 int err;
91 struct clk *clk_m;
92 int rate;
77 93
78 srate = params_rate(params); 94 srate = params_rate(params);
79 switch (srate) { 95 switch (srate) {
@@ -86,29 +102,60 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
86 mclk = 256 * srate; 102 mclk = 256 * srate;
87 break; 103 break;
88 } 104 }
105
106
107
108 clk_m = clk_get_sys(NULL, "clk_m");
109 if (IS_ERR(clk_m)) {
110 dev_err(card->dev, "Can't retrieve clk clk_m\n");
111 err = PTR_ERR(clk_m);
112 return err;
113 }
114 rate = clk_get_rate(clk_m);
115 printk("extern1 rate=%d\n",rate);
116
117#if TEGRA30_I2S_MASTER_PLAYBACK
89 /* FIXME: Codec only requires >= 3MHz if OSR==0 */ 118 /* FIXME: Codec only requires >= 3MHz if OSR==0 */
90 while (mclk < 6000000) 119 while (mclk < 6000000)
91 mclk *= 2; 120 mclk *= 2;
92 121
122 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
123 SND_SOC_DAIFMT_CBS_CFS;
124#else
125 mclk = rate;
126
127 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
128 SND_SOC_DAIFMT_CBM_CFM;
129#endif
130
131
93 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); 132 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
94 if (err < 0) { 133 if (err < 0) {
95 dev_err(card->dev, "Can't configure clocks\n"); 134 if (!(machine->util_data.set_mclk % mclk))
96 return err; 135 mclk = machine->util_data.set_mclk;
136 else {
137 dev_err(card->dev, "Can't configure clocks\n");
138 return err;
139 }
97 } 140 }
98 141
99 err = snd_soc_dai_set_fmt(codec_dai, 142 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
100 SND_SOC_DAIFMT_I2S | 143
101 SND_SOC_DAIFMT_NB_NF | 144 /* Use DSP mode for mono on Tegra20 */
102 SND_SOC_DAIFMT_CBS_CFS); 145 if ((params_channels(params) != 2) &&
146 (machine_is_ventana() || machine_is_harmony() ||
147 machine_is_kaen() || machine_is_aebl()))
148 i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
149 else
150 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
151
152 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
103 if (err < 0) { 153 if (err < 0) {
104 dev_err(card->dev, "codec_dai fmt not set\n"); 154 dev_err(card->dev, "codec_dai fmt not set\n");
105 return err; 155 return err;
106 } 156 }
107 157
108 err = snd_soc_dai_set_fmt(cpu_dai, 158 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
109 SND_SOC_DAIFMT_I2S |
110 SND_SOC_DAIFMT_NB_NF |
111 SND_SOC_DAIFMT_CBS_CFS);
112 if (err < 0) { 159 if (err < 0) {
113 dev_err(card->dev, "cpu_dai fmt not set\n"); 160 dev_err(card->dev, "cpu_dai fmt not set\n");
114 return err; 161 return err;
@@ -121,22 +168,167 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
121 return err; 168 return err;
122 } 169 }
123 170
171#ifdef CONFIG_ARCH_TEGRA_2x_SOC
172 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
173 TEGRA20_DAS_DAP_ID_1);
174 if (err < 0) {
175 dev_err(card->dev, "failed to set dap-dac path\n");
176 return err;
177 }
178
179 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
180 TEGRA20_DAS_DAP_SEL_DAC1);
181 if (err < 0) {
182 dev_err(card->dev, "failed to set dac-dap path\n");
183 return err;
184 }
185#endif
186 return 0;
187}
188
189static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
190 struct snd_pcm_hw_params *params)
191{
192 struct snd_soc_pcm_runtime *rtd = substream->private_data;
193 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
194 struct snd_soc_card *card = rtd->card;
195 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
196 int srate, mclk, min_mclk;
197 int err;
198
199 srate = params_rate(params);
200 switch (srate) {
201 case 11025:
202 case 22050:
203 case 44100:
204 case 88200:
205 mclk = 11289600;
206 break;
207 case 8000:
208 case 16000:
209 case 32000:
210 case 48000:
211 case 64000:
212 case 96000:
213 mclk = 12288000;
214 break;
215 default:
216 return -EINVAL;
217 }
218 min_mclk = 64 * srate;
219
220 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
221 if (err < 0) {
222 if (!(machine->util_data.set_mclk % min_mclk))
223 mclk = machine->util_data.set_mclk;
224 else {
225 dev_err(card->dev, "Can't configure clocks\n");
226 return err;
227 }
228 }
229
230 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
231
232 err = snd_soc_dai_set_fmt(cpu_dai,
233 SND_SOC_DAIFMT_DSP_A |
234 SND_SOC_DAIFMT_NB_NF |
235 SND_SOC_DAIFMT_CBS_CFS);
236 if (err < 0) {
237 dev_err(card->dev, "cpu_dai fmt not set\n");
238 return err;
239 }
240
241#ifdef CONFIG_ARCH_TEGRA_2x_SOC
242 err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
243 TEGRA20_DAS_DAP_ID_4);
244 if (err < 0) {
245 dev_err(card->dev, "failed to set dac-dap path\n");
246 return err;
247 }
248
249 err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
250 TEGRA20_DAS_DAP_SEL_DAC2);
251 if (err < 0) {
252 dev_err(card->dev, "failed to set dac-dap path\n");
253 return err;
254 }
255#endif
256 return 0;
257}
258
259static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
260 struct snd_pcm_hw_params *params)
261{
262 struct snd_soc_pcm_runtime *rtd = substream->private_data;
263 struct snd_soc_card *card = rtd->card;
264 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
265 int srate, mclk, min_mclk;
266 int err;
267
268 srate = params_rate(params);
269 switch (srate) {
270 case 11025:
271 case 22050:
272 case 44100:
273 case 88200:
274 mclk = 11289600;
275 break;
276 case 8000:
277 case 16000:
278 case 32000:
279 case 48000:
280 case 64000:
281 case 96000:
282 mclk = 12288000;
283 break;
284 default:
285 return -EINVAL;
286 }
287 min_mclk = 128 * srate;
288
289 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
290 if (err < 0) {
291 if (!(machine->util_data.set_mclk % min_mclk))
292 mclk = machine->util_data.set_mclk;
293 else {
294 dev_err(card->dev, "Can't configure clocks\n");
295 return err;
296 }
297 }
298
299 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
300
301 return 0;
302}
303
304static int tegra_hw_free(struct snd_pcm_substream *substream)
305{
306 struct snd_soc_pcm_runtime *rtd = substream->private_data;
307 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(rtd->card);
308
309 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
310
124 return 0; 311 return 0;
125} 312}
126 313
127static struct snd_soc_ops tegra_wm8903_ops = { 314static struct snd_soc_ops tegra_wm8903_ops = {
128 .hw_params = tegra_wm8903_hw_params, 315 .hw_params = tegra_wm8903_hw_params,
316 .hw_free = tegra_hw_free,
129}; 317};
130 318
131static struct snd_soc_jack tegra_wm8903_hp_jack; 319static struct snd_soc_ops tegra_wm8903_bt_sco_ops = {
320 .hw_params = tegra_bt_sco_hw_params,
321 .hw_free = tegra_hw_free,
322};
132 323
133static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = { 324static struct snd_soc_ops tegra_spdif_ops = {
134 { 325 .hw_params = tegra_spdif_hw_params,
135 .pin = "Headphone Jack", 326 .hw_free = tegra_hw_free,
136 .mask = SND_JACK_HEADPHONE,
137 },
138}; 327};
139 328
329static struct snd_soc_jack tegra_wm8903_hp_jack;
330static struct snd_soc_jack tegra_wm8903_mic_jack;
331
140static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = { 332static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = {
141 .name = "headphone detect", 333 .name = "headphone detect",
142 .report = SND_JACK_HEADPHONE, 334 .report = SND_JACK_HEADPHONE,
@@ -144,7 +336,63 @@ static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = {
144 .invert = 1, 336 .invert = 1,
145}; 337};
146 338
147static struct snd_soc_jack tegra_wm8903_mic_jack; 339#ifdef CONFIG_SWITCH
340/* These values are copied from Android WiredAccessoryObserver */
341enum headset_state {
342 BIT_NO_HEADSET = 0,
343 BIT_HEADSET = (1 << 0),
344 BIT_HEADSET_NO_MIC = (1 << 1),
345};
346
347static struct switch_dev tegra_wm8903_headset_switch = {
348 .name = "h2w",
349};
350
351static int tegra_wm8903_jack_notifier(struct notifier_block *self,
352 unsigned long action, void *dev)
353{
354 struct snd_soc_jack *jack = dev;
355 struct snd_soc_codec *codec = jack->codec;
356 struct snd_soc_card *card = codec->card;
357 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
358 enum headset_state state = BIT_NO_HEADSET;
359
360 if (jack == &tegra_wm8903_hp_jack) {
361 machine->jack_status &= ~SND_JACK_HEADPHONE;
362 machine->jack_status |= (action & SND_JACK_HEADPHONE);
363 } else {
364 machine->jack_status &= ~SND_JACK_MICROPHONE;
365 machine->jack_status |= (action & SND_JACK_MICROPHONE);
366 }
367
368 switch (machine->jack_status) {
369 case SND_JACK_HEADPHONE:
370 state = BIT_HEADSET_NO_MIC;
371 break;
372 case SND_JACK_HEADSET:
373 state = BIT_HEADSET;
374 break;
375 case SND_JACK_MICROPHONE:
376 /* mic: would not report */
377 default:
378 state = BIT_NO_HEADSET;
379 }
380
381 switch_set_state(&tegra_wm8903_headset_switch, state);
382
383 return NOTIFY_OK;
384}
385
386static struct notifier_block tegra_wm8903_jack_detect_nb = {
387 .notifier_call = tegra_wm8903_jack_notifier,
388};
389#else
390static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = {
391 {
392 .pin = "Headphone Jack",
393 .mask = SND_JACK_HEADPHONE,
394 },
395};
148 396
149static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = { 397static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = {
150 { 398 {
@@ -152,6 +400,7 @@ static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = {
152 .mask = SND_JACK_MICROPHONE, 400 .mask = SND_JACK_MICROPHONE,
153 }, 401 },
154}; 402};
403#endif
155 404
156static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, 405static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
157 struct snd_kcontrol *k, int event) 406 struct snd_kcontrol *k, int event)
@@ -161,6 +410,13 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
161 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 410 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
162 struct tegra_wm8903_platform_data *pdata = machine->pdata; 411 struct tegra_wm8903_platform_data *pdata = machine->pdata;
163 412
413 if (machine->spk_reg) {
414 if (SND_SOC_DAPM_EVENT_ON(event))
415 regulator_enable(machine->spk_reg);
416 else
417 regulator_disable(machine->spk_reg);
418 }
419
164 if (!(machine->gpio_requested & GPIO_SPKR_EN)) 420 if (!(machine->gpio_requested & GPIO_SPKR_EN))
165 return 0; 421 return 0;
166 422
@@ -187,7 +443,57 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
187 return 0; 443 return 0;
188} 444}
189 445
190static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = { 446static int tegra_wm8903_event_int_mic(struct snd_soc_dapm_widget *w,
447 struct snd_kcontrol *k, int event)
448{
449 struct snd_soc_dapm_context *dapm = w->dapm;
450 struct snd_soc_card *card = dapm->card;
451 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
452 struct tegra_wm8903_platform_data *pdata = machine->pdata;
453
454 if (machine->dmic_reg) {
455 if (SND_SOC_DAPM_EVENT_ON(event))
456 regulator_enable(machine->dmic_reg);
457 else
458 regulator_disable(machine->dmic_reg);
459 }
460
461 if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
462 return 0;
463
464 gpio_set_value_cansleep(pdata->gpio_int_mic_en,
465 SND_SOC_DAPM_EVENT_ON(event));
466
467 return 0;
468}
469
470static int tegra_wm8903_event_ext_mic(struct snd_soc_dapm_widget *w,
471 struct snd_kcontrol *k, int event)
472{
473 struct snd_soc_dapm_context *dapm = w->dapm;
474 struct snd_soc_card *card = dapm->card;
475 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
476 struct tegra_wm8903_platform_data *pdata = machine->pdata;
477
478 if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
479 return 0;
480
481 gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
482 SND_SOC_DAPM_EVENT_ON(event));
483
484 return 0;
485}
486
487static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
488 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
489 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
490 SND_SOC_DAPM_LINE("LineOut", NULL),
491 SND_SOC_DAPM_MIC("Mic Jack", tegra_wm8903_event_ext_mic),
492 SND_SOC_DAPM_MIC("Int Mic", tegra_wm8903_event_int_mic),
493 SND_SOC_DAPM_LINE("Line In", NULL),
494};
495
496static const struct snd_soc_dapm_widget tegra_wm8903_default_dapm_widgets[] = {
191 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk), 497 SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
192 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp), 498 SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
193 SND_SOC_DAPM_MIC("Mic Jack", NULL), 499 SND_SOC_DAPM_MIC("Mic Jack", NULL),
@@ -204,6 +510,24 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
204 {"IN1L", NULL, "Mic Bias"}, 510 {"IN1L", NULL, "Mic Bias"},
205}; 511};
206 512
513static const struct snd_soc_dapm_route cardhu_audio_map[] = {
514 {"Headphone Jack", NULL, "HPOUTR"},
515 {"Headphone Jack", NULL, "HPOUTL"},
516 {"Int Spk", NULL, "ROP"},
517 {"Int Spk", NULL, "RON"},
518 {"Int Spk", NULL, "LOP"},
519 {"Int Spk", NULL, "LON"},
520 {"LineOut", NULL, "LINEOUTL"},
521 {"LineOut", NULL, "LINEOUTR"},
522 {"Mic Bias", NULL, "Mic Jack"},
523 {"IN1L", NULL, "Mic Bias"},
524 {"Mic Bias", NULL, "Int Mic"},
525 {"IN1L", NULL, "Mic Bias"},
526 {"IN1R", NULL, "Mic Bias"},
527 {"IN3L", NULL, "Line In"},
528 {"IN3R", NULL, "Line In"},
529};
530
207static const struct snd_soc_dapm_route seaboard_audio_map[] = { 531static const struct snd_soc_dapm_route seaboard_audio_map[] = {
208 {"Headphone Jack", NULL, "HPOUTR"}, 532 {"Headphone Jack", NULL, "HPOUTR"},
209 {"Headphone Jack", NULL, "HPOUTL"}, 533 {"Headphone Jack", NULL, "HPOUTL"},
@@ -235,7 +559,16 @@ static const struct snd_soc_dapm_route aebl_audio_map[] = {
235 {"IN1R", NULL, "Mic Bias"}, 559 {"IN1R", NULL, "Mic Bias"},
236}; 560};
237 561
238static const struct snd_kcontrol_new tegra_wm8903_controls[] = { 562static const struct snd_kcontrol_new cardhu_controls[] = {
563 SOC_DAPM_PIN_SWITCH("Int Spk"),
564 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
565 SOC_DAPM_PIN_SWITCH("LineOut"),
566 SOC_DAPM_PIN_SWITCH("Mic Jack"),
567 SOC_DAPM_PIN_SWITCH("Int Mic"),
568 SOC_DAPM_PIN_SWITCH("Line In"),
569};
570
571static const struct snd_kcontrol_new tegra_wm8903_default_controls[] = {
239 SOC_DAPM_PIN_SWITCH("Int Spk"), 572 SOC_DAPM_PIN_SWITCH("Int Spk"),
240}; 573};
241 574
@@ -248,6 +581,8 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
248 struct tegra_wm8903_platform_data *pdata = machine->pdata; 581 struct tegra_wm8903_platform_data *pdata = machine->pdata;
249 int ret; 582 int ret;
250 583
584 machine->bias_level = SND_SOC_BIAS_STANDBY;
585
251 if (gpio_is_valid(pdata->gpio_spkr_en)) { 586 if (gpio_is_valid(pdata->gpio_spkr_en)) {
252 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); 587 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
253 if (ret) { 588 if (ret) {
@@ -267,7 +602,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
267 } 602 }
268 machine->gpio_requested |= GPIO_HP_MUTE; 603 machine->gpio_requested |= GPIO_HP_MUTE;
269 604
270 gpio_direction_output(pdata->gpio_hp_mute, 0); 605 gpio_direction_output(pdata->gpio_hp_mute, 1);
271 } 606 }
272 607
273 if (gpio_is_valid(pdata->gpio_int_mic_en)) { 608 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
@@ -298,28 +633,41 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
298 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; 633 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
299 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, 634 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
300 &tegra_wm8903_hp_jack); 635 &tegra_wm8903_hp_jack);
636#ifndef CONFIG_SWITCH
301 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, 637 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
302 ARRAY_SIZE(tegra_wm8903_hp_jack_pins), 638 ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
303 tegra_wm8903_hp_jack_pins); 639 tegra_wm8903_hp_jack_pins);
640#else
641 snd_soc_jack_notifier_register(&tegra_wm8903_hp_jack,
642 &tegra_wm8903_jack_detect_nb);
643#endif
304 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 644 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
305 1, 645 1,
306 &tegra_wm8903_hp_jack_gpio); 646 &tegra_wm8903_hp_jack_gpio);
647 machine->gpio_requested |= GPIO_HP_DET;
307 } 648 }
308 649
309 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, 650 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
310 &tegra_wm8903_mic_jack); 651 &tegra_wm8903_mic_jack);
652#ifndef CONFIG_SWITCH
311 snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, 653 snd_soc_jack_add_pins(&tegra_wm8903_mic_jack,
312 ARRAY_SIZE(tegra_wm8903_mic_jack_pins), 654 ARRAY_SIZE(tegra_wm8903_mic_jack_pins),
313 tegra_wm8903_mic_jack_pins); 655 tegra_wm8903_mic_jack_pins);
656#else
657 snd_soc_jack_notifier_register(&tegra_wm8903_mic_jack,
658 &tegra_wm8903_jack_detect_nb);
659#endif
314 wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, 660 wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
315 0); 661 machine_is_cardhu() ? SND_JACK_MICROPHONE : 0);
316 662
317 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); 663 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
318 664
319 /* FIXME: Calculate automatically based on DAPM routes? */ 665 /* FIXME: Calculate automatically based on DAPM routes? */
320 if (!machine_is_harmony() && !machine_is_ventana()) 666 if (!machine_is_harmony() && !machine_is_ventana() &&
667 !machine_is_cardhu())
321 snd_soc_dapm_nc_pin(dapm, "IN1L"); 668 snd_soc_dapm_nc_pin(dapm, "IN1L");
322 if (!machine_is_seaboard() && !machine_is_aebl()) 669 if (!machine_is_seaboard() && !machine_is_aebl() &&
670 !machine_is_cardhu())
323 snd_soc_dapm_nc_pin(dapm, "IN1R"); 671 snd_soc_dapm_nc_pin(dapm, "IN1R");
324 snd_soc_dapm_nc_pin(dapm, "IN2L"); 672 snd_soc_dapm_nc_pin(dapm, "IN2L");
325 if (!machine_is_kaen()) 673 if (!machine_is_kaen())
@@ -342,26 +690,98 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
342 return 0; 690 return 0;
343} 691}
344 692
345static struct snd_soc_dai_link tegra_wm8903_dai = { 693#ifdef WM8903_SET_BIAS_LEVEL
346 .name = "WM8903", 694static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
347 .stream_name = "WM8903 PCM", 695 enum snd_soc_bias_level level)
348 .codec_name = "wm8903.0-001a", 696{
349 .platform_name = "tegra-pcm-audio", 697 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
350 .cpu_dai_name = "tegra-i2s.0", 698
351 .codec_dai_name = "wm8903-hifi", 699 if (machine->bias_level == SND_SOC_BIAS_OFF &&
352 .init = tegra_wm8903_init, 700 level != SND_SOC_BIAS_OFF)
353 .ops = &tegra_wm8903_ops, 701 tegra_asoc_utils_clk_enable(&machine->util_data);
702
703 return 0;
704}
705
706static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
707 enum snd_soc_bias_level level)
708{
709 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
710
711 if (machine->bias_level != SND_SOC_BIAS_OFF &&
712 level == SND_SOC_BIAS_OFF)
713 tegra_asoc_utils_clk_disable(&machine->util_data);
714
715 machine->bias_level = level;
716
717 return 0 ;
718}
719#endif
720
721static struct snd_soc_dai_link tegra_wm8903_dai[] = {
722 {
723 .name = "WM8903",
724 .stream_name = "WM8903 PCM",
725 .codec_name = "wm8903.0-001a",
726 .platform_name = "tegra-pcm-audio",
727 .cpu_dai_name = "tegra20-i2s.0",
728 .codec_dai_name = "wm8903-hifi",
729 .init = tegra_wm8903_init,
730 .ops = &tegra_wm8903_ops,
731 },
732 {
733 .name = "SPDIF",
734 .stream_name = "SPDIF PCM",
735 .codec_name = "spdif-dit.0",
736 .platform_name = "tegra-pcm-audio",
737 .cpu_dai_name = "tegra20-spdif",
738 .codec_dai_name = "dit-hifi",
739 .ops = &tegra_spdif_ops,
740 },
741 {
742 .name = "BT-SCO",
743 .stream_name = "BT SCO PCM",
744 .codec_name = "spdif-dit.1",
745 .platform_name = "tegra-pcm-audio",
746 .cpu_dai_name = "tegra20-i2s.1",
747 .codec_dai_name = "dit-hifi",
748 .ops = &tegra_wm8903_bt_sco_ops,
749 },
354}; 750};
355 751
752static int tegra_wm8903_suspend_post(struct snd_soc_card *card)
753{
754 struct snd_soc_jack_gpio *gpio = &tegra_wm8903_hp_jack_gpio;
755
756 if (gpio_is_valid(gpio->gpio))
757 disable_irq(gpio_to_irq(gpio->gpio));
758
759 return 0;
760}
761
762static int tegra_wm8903_resume_pre(struct snd_soc_card *card)
763{
764 int val;
765 struct snd_soc_jack_gpio *gpio = &tegra_wm8903_hp_jack_gpio;
766
767 if (gpio_is_valid(gpio->gpio)) {
768 val = gpio_get_value(gpio->gpio);
769 val = gpio->invert ? !val : val;
770 snd_soc_jack_report(gpio->jack, val, gpio->report);
771 enable_irq(gpio_to_irq(gpio->gpio));
772 }
773
774 return 0;
775}
776
356static struct snd_soc_card snd_soc_tegra_wm8903 = { 777static struct snd_soc_card snd_soc_tegra_wm8903 = {
357 .name = "tegra-wm8903", 778 .name = "tegra-wm8903",
358 .dai_link = &tegra_wm8903_dai, 779 .dai_link = tegra_wm8903_dai,
359 .num_links = 1, 780 .num_links = ARRAY_SIZE(tegra_wm8903_dai),
360 781 .suspend_post = tegra_wm8903_suspend_post,
361 .controls = tegra_wm8903_controls, 782 .resume_pre = tegra_wm8903_resume_pre,
362 .num_controls = ARRAY_SIZE(tegra_wm8903_controls), 783 //.set_bias_level = tegra30_soc_set_bias_level,
363 .dapm_widgets = tegra_wm8903_dapm_widgets, 784 //.set_bias_level_post = tegra30_soc_set_bias_level_post,
364 .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
365}; 785};
366 786
367static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) 787static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
@@ -389,13 +809,63 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
389 if (ret) 809 if (ret)
390 goto err_free_machine; 810 goto err_free_machine;
391 811
812 if (machine_is_cardhu() || machine_is_ventana()) {
813 machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
814 if (IS_ERR(machine->spk_reg)) {
815 dev_info(&pdev->dev, "No speaker regulator found\n");
816 machine->spk_reg = 0;
817 }
818 }
819
820 if (machine_is_ventana()) {
821 machine->dmic_reg = regulator_get(&pdev->dev, "vdd_dmic");
822 if (IS_ERR(machine->dmic_reg)) {
823 dev_info(&pdev->dev, "No digital mic"
824 " regulator found\n");
825 machine->dmic_reg = 0;
826 }
827 }
828
829 if (machine_is_cardhu()) {
830 tegra_wm8903_dai[0].codec_name = "wm8903.4-001a",
831 tegra_wm8903_dai[0].cpu_dai_name = "tegra30-i2s.1";
832
833 tegra_wm8903_dai[1].cpu_dai_name = "tegra30-spdif";
834
835 tegra_wm8903_dai[2].cpu_dai_name = "tegra30-i2s.3";
836 }
837
838#ifdef CONFIG_SWITCH
839 /* Addd h2w swith class support */
840 ret = switch_dev_register(&tegra_wm8903_headset_switch);
841 if (ret < 0)
842 goto err_fini_utils;
843#endif
844
392 card->dev = &pdev->dev; 845 card->dev = &pdev->dev;
393 platform_set_drvdata(pdev, card); 846 platform_set_drvdata(pdev, card);
394 snd_soc_card_set_drvdata(card, machine); 847 snd_soc_card_set_drvdata(card, machine);
395 848
396 if (machine_is_harmony() || machine_is_ventana()) { 849 if (machine_is_cardhu() || machine_is_ventana()) {
850 card->controls = cardhu_controls;
851 card->num_controls = ARRAY_SIZE(cardhu_controls);
852
853 card->dapm_widgets = cardhu_dapm_widgets;
854 card->num_dapm_widgets = ARRAY_SIZE(cardhu_dapm_widgets);
855 } else {
856 card->controls = tegra_wm8903_default_controls;
857 card->num_controls = ARRAY_SIZE(tegra_wm8903_default_controls);
858
859 card->dapm_widgets = tegra_wm8903_default_dapm_widgets;
860 card->num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_default_dapm_widgets);
861 }
862
863 if (machine_is_harmony()) {
397 card->dapm_routes = harmony_audio_map; 864 card->dapm_routes = harmony_audio_map;
398 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); 865 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
866 } else if (machine_is_ventana() || machine_is_cardhu()) {
867 card->dapm_routes = cardhu_audio_map;
868 card->num_dapm_routes = ARRAY_SIZE(cardhu_audio_map);
399 } else if (machine_is_seaboard()) { 869 } else if (machine_is_seaboard()) {
400 card->dapm_routes = seaboard_audio_map; 870 card->dapm_routes = seaboard_audio_map;
401 card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); 871 card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
@@ -411,11 +881,24 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
411 if (ret) { 881 if (ret) {
412 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", 882 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
413 ret); 883 ret);
414 goto err_fini_utils; 884 goto err_unregister_switch;
885 }
886
887 if (!card->instantiated) {
888 ret = -ENODEV;
889 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
890 ret);
891 goto err_unregister_card;
415 } 892 }
416 893
417 return 0; 894 return 0;
418 895
896err_unregister_card:
897 snd_soc_unregister_card(card);
898err_unregister_switch:
899#ifdef CONFIG_SWITCH
900 switch_dev_unregister(&tegra_wm8903_headset_switch);
901#endif
419err_fini_utils: 902err_fini_utils:
420 tegra_asoc_utils_fini(&machine->util_data); 903 tegra_asoc_utils_fini(&machine->util_data);
421err_free_machine: 904err_free_machine:
@@ -429,10 +912,10 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
429 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 912 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
430 struct tegra_wm8903_platform_data *pdata = machine->pdata; 913 struct tegra_wm8903_platform_data *pdata = machine->pdata;
431 914
432 snd_soc_unregister_card(card); 915 if (machine->gpio_requested & GPIO_HP_DET)
433 916 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
434 tegra_asoc_utils_fini(&machine->util_data); 917 1,
435 918 &tegra_wm8903_hp_jack_gpio);
436 if (machine->gpio_requested & GPIO_EXT_MIC_EN) 919 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
437 gpio_free(pdata->gpio_ext_mic_en); 920 gpio_free(pdata->gpio_ext_mic_en);
438 if (machine->gpio_requested & GPIO_INT_MIC_EN) 921 if (machine->gpio_requested & GPIO_INT_MIC_EN)
@@ -441,7 +924,20 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
441 gpio_free(pdata->gpio_hp_mute); 924 gpio_free(pdata->gpio_hp_mute);
442 if (machine->gpio_requested & GPIO_SPKR_EN) 925 if (machine->gpio_requested & GPIO_SPKR_EN)
443 gpio_free(pdata->gpio_spkr_en); 926 gpio_free(pdata->gpio_spkr_en);
927 machine->gpio_requested = 0;
928
929 if (machine->spk_reg)
930 regulator_put(machine->spk_reg);
931 if (machine->dmic_reg)
932 regulator_put(machine->dmic_reg);
933
934 snd_soc_unregister_card(card);
935
936 tegra_asoc_utils_fini(&machine->util_data);
444 937
938#ifdef CONFIG_SWITCH
939 switch_dev_unregister(&tegra_wm8903_headset_switch);
940#endif
445 kfree(machine); 941 kfree(machine);
446 942
447 return 0; 943 return 0;