diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:46:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:46:37 -0400 |
commit | d3e458d78167102cc961237cfceef6fffc80c0b3 (patch) | |
tree | e9195c1294daf053614e63ac52b0b44a28479017 /sound/soc/tegra/tegra_das.c | |
parent | f2e1fbb5f2177227f71c4fc0491e531dd7acd385 (diff) | |
parent | d351cf4603edb2a5bfa9a48d06c425511c63f2a3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (308 commits)
ALSA: sound/pci/asihpi: check adapter index in hpi_ioctl
ALSA: aloop - Fix possible IRQ lock inversion
ALSA: sound/core: merge list_del()/list_add_tail() to list_move_tail()
ALSA: ctxfi - use list_move() instead of list_del()/list_add() combination
ALSA: firewire - msleep needs delay.h
ALSA: firewire-lib, firewire-speakers: handle packet queueing errors
ALSA: firewire-lib: allocate DMA buffer separately
ALSA: firewire-lib: use no-info SYT for packets without SYT sample
ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver
ALSA: hda - Remove an unused variable in patch_realtek.c
ALSA: hda - pin-adc-mux-dmic auto-configuration of 92HD8X codecs
ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
ALSA: hda - Move default input-src selection to init part
ALSA: hda - Initialize special cases for input src in init phase
ALSA: ctxfi - Clear input settings before initialization
ALSA: ctxfi - Fix SPDIF status retrieval
ALSA: ctxfi - Fix incorrect SPDIF status bit mask
ALSA: ctxfi - Fix microphone boost codes/comments
ALSA: atiixp - Fix wrong time-out checks during ac-link reset
ALSA: intel8x0m: append 'm' to "r_intel8x0"
...
Diffstat (limited to 'sound/soc/tegra/tegra_das.c')
-rw-r--r-- | sound/soc/tegra/tegra_das.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c new file mode 100644 index 000000000000..9f24ef73f2cb --- /dev/null +++ b/sound/soc/tegra/tegra_das.c | |||
@@ -0,0 +1,265 @@ | |||
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 | |||
36 | static struct tegra_das *das; | ||
37 | |||
38 | static inline void tegra_das_write(u32 reg, u32 val) | ||
39 | { | ||
40 | __raw_writel(val, das->regs + reg); | ||
41 | } | ||
42 | |||
43 | static inline u32 tegra_das_read(u32 reg) | ||
44 | { | ||
45 | return __raw_readl(das->regs + reg); | ||
46 | } | ||
47 | |||
48 | int 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 | } | ||
64 | EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac); | ||
65 | |||
66 | int 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 | } | ||
86 | EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap); | ||
87 | |||
88 | int 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 | } | ||
106 | EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap); | ||
107 | |||
108 | #ifdef CONFIG_DEBUG_FS | ||
109 | static 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 | |||
133 | static 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 | |||
138 | static 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 | |||
145 | static 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 | |||
152 | static void tegra_das_debug_remove(struct tegra_das *das) | ||
153 | { | ||
154 | if (das->debug) | ||
155 | debugfs_remove(das->debug); | ||
156 | } | ||
157 | #else | ||
158 | static inline void tegra_das_debug_add(struct tegra_das *das) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | static inline void tegra_das_debug_remove(struct tegra_das *das) | ||
163 | { | ||
164 | } | ||
165 | #endif | ||
166 | |||
167 | static 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 | |||
211 | err_release: | ||
212 | release_mem_region(res->start, resource_size(res)); | ||
213 | err_free: | ||
214 | kfree(das); | ||
215 | das = 0; | ||
216 | exit: | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static 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 | |||
242 | static 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 | |||
250 | static int __init tegra_das_modinit(void) | ||
251 | { | ||
252 | return platform_driver_register(&tegra_das_driver); | ||
253 | } | ||
254 | module_init(tegra_das_modinit); | ||
255 | |||
256 | static void __exit tegra_das_modexit(void) | ||
257 | { | ||
258 | platform_driver_unregister(&tegra_das_driver); | ||
259 | } | ||
260 | module_exit(tegra_das_modexit); | ||
261 | |||
262 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
263 | MODULE_DESCRIPTION("Tegra DAS driver"); | ||
264 | MODULE_LICENSE("GPL"); | ||
265 | MODULE_ALIAS("platform:" DRV_NAME); | ||