]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/board-n800-audio.c
ARM: OMAP: Merge board specific files from N800 tree
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / board-n800-audio.c
1 /*
2  * linux/arch/arm/mach-omap2/board-n800-audio.c
3  *
4  * Copyright (C) 2006 Nokia Corporation
5  * Contact: Juha Yrjola
6  *          Jarkko Nikula <jarkko.nikula@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/err.h>
25 #include <linux/clk.h>
26 #include <linux/platform_device.h>
27 #include <linux/spi/tsc2301.h>
28
29 #include <asm/io.h>
30 #include <asm/arch/eac.h>
31
32 #include "../plat-omap/dsp/dsp_common.h"
33
34 #if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC)
35 #define AUDIO_ENABLED
36
37 static struct clk *sys_clkout2;
38 static struct clk *func96m_clk;
39 static struct device *eac_device;
40 static struct device *tsc2301_device;
41
42 static int enable_audio;
43 static int audio_ok;
44 static spinlock_t audio_lock;
45
46 /*
47  * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results
48  * in about 2 mA extra current leak when audios are powered down. The
49  * workaround is to multiplex them to protected mode (with pull-ups enabled)
50  * whenever audio is not being used.
51  */
52 static int eac_mux_disabled = 0;
53 static int clkout2_mux_disabled = 0;
54 static u32 saved_mux[2];
55
56 static void n800_enable_eac_mux(void)
57 {
58         if (!eac_mux_disabled)
59                 return;
60         __raw_writel(saved_mux[1], IO_ADDRESS(0x48000124));
61         eac_mux_disabled = 0;
62 }
63
64 static void n800_disable_eac_mux(void)
65 {
66         if (eac_mux_disabled) {
67                 WARN_ON(eac_mux_disabled);
68                 return;
69         }
70         saved_mux[1] = __raw_readl(IO_ADDRESS(0x48000124));
71         __raw_writel(0x1f1f1f1f, IO_ADDRESS(0x48000124));
72         eac_mux_disabled = 1;
73 }
74
75 static void n800_enable_clkout2_mux(void)
76 {
77         if (!clkout2_mux_disabled)
78                 return;
79         __raw_writel(saved_mux[0], IO_ADDRESS(0x480000e8));
80         clkout2_mux_disabled = 0;
81 }
82
83 static void n800_disable_clkout2_mux(void)
84 {
85         u32 l;
86
87         if (clkout2_mux_disabled) {
88                 WARN_ON(clkout2_mux_disabled);
89                 return;
90         }
91         saved_mux[0] = __raw_readl(IO_ADDRESS(0x480000e8));
92         l = saved_mux[0] & ~0xff;
93         l |= 0x1f;
94         __raw_writel(l, IO_ADDRESS(0x480000e8));
95         clkout2_mux_disabled = 1;
96 }
97
98 static int n800_eac_enable_ext_clocks(struct device *dev)
99 {
100         BUG_ON(tsc2301_device == NULL);
101         n800_enable_eac_mux();
102         tsc2301_mixer_enable_mclk(tsc2301_device);
103
104         return 0;
105 }
106
107 static void n800_eac_disable_ext_clocks(struct device *dev)
108 {
109         BUG_ON(tsc2301_device == NULL);
110         tsc2301_mixer_disable_mclk(tsc2301_device);
111         n800_disable_eac_mux();
112 }
113
114 static int n800_audio_set_power(void *pdata, int dac, int adc)
115 {
116         BUG_ON(pdata != tsc2301_device);
117         tsc2301_mixer_set_power(tsc2301_device, dac, adc);
118
119         return 0;
120 }
121
122 static int n800_audio_register_controls(void *pdata, struct snd_card *card)
123 {
124         BUG_ON(pdata != tsc2301_device);
125         return tsc2301_mixer_register_controls(tsc2301_device, card);
126 }
127
128 static struct eac_codec n800_eac_codec = {
129         .mclk_src = EAC_MCLK_EXT_2x12288000,
130         .codec_mode = EAC_CODEC_I2S,
131         .codec_conf.i2s.polarity_changed_mode = 0,
132         .codec_conf.i2s.sync_delay_enable = 0,
133         .default_rate = 48000,
134         .set_power = n800_audio_set_power,
135         .register_controls = n800_audio_register_controls,
136         .short_name = "TSC2301",
137 };
138
139 static int n800_register_codec(void)
140 {
141         int r, do_enable = 0;
142         unsigned long flags;
143
144         n800_eac_codec.private_data = tsc2301_device;
145         r = eac_register_codec(eac_device, &n800_eac_codec);
146         if (r < 0)
147                 return r;
148         spin_lock_irqsave(&audio_lock, flags);
149         audio_ok = 1;
150         if (enable_audio)
151                 do_enable = 1;
152         spin_unlock_irqrestore(&audio_lock, flags);
153         if (do_enable)
154                 eac_set_mode(eac_device, 1, 1);
155         return 0;
156 }
157
158 static void n800_unregister_codec(void)
159 {
160         audio_ok = 0;
161         eac_unregister_codec(eac_device);
162         eac_set_mode(eac_device, 0, 0);
163 }
164
165 static int n800_eac_init(struct device *dev)
166 {
167         int r;
168
169         BUG_ON(eac_device != NULL);
170         eac_device = dev;
171         if (tsc2301_device != NULL) {
172                 r = n800_register_codec();
173                 if (r < 0)
174                         return r;
175         }
176
177         return 0;
178 }
179
180 static void n800_eac_cleanup(struct device *dev)
181 {
182         eac_device = NULL;
183         if (tsc2301_device != NULL)
184                 n800_unregister_codec();
185 }
186
187 static int n800_codec_get_clocks(struct device *dev)
188 {
189         sys_clkout2 = clk_get(dev, "sys_clkout2");
190         if (IS_ERR(sys_clkout2)) {
191                 dev_err(dev, "Could not get sys_clkout2\n");
192                 return -ENODEV;
193         }
194         /* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
195          * 96 MHz as its parent in order to get 12 MHz */
196         func96m_clk = clk_get(dev, "func_96m_ck");
197         if (IS_ERR(func96m_clk)) {
198                 dev_err(dev, "Could not get func 96M clock\n");
199                 clk_put(sys_clkout2);
200                 return -ENODEV;
201         }
202
203         clk_set_parent(sys_clkout2, func96m_clk);
204         clk_set_rate(sys_clkout2, 12000000);
205
206         return 0;
207 }
208
209 static void n800_codec_put_clocks(struct device *dev)
210 {
211         clk_put(func96m_clk);
212         clk_put(sys_clkout2);
213 }
214
215 static int n800_codec_enable_clock(struct device *dev)
216 {
217         n800_enable_clkout2_mux();
218         return clk_enable(sys_clkout2);
219 }
220
221 static void n800_codec_disable_clock(struct device *dev)
222 {
223         clk_disable(sys_clkout2);
224         n800_disable_clkout2_mux();
225 }
226
227 static int n800_codec_init(struct device *dev)
228 {
229         int r;
230
231         BUG_ON(tsc2301_device != NULL);
232         tsc2301_device = dev;
233         if ((r = n800_codec_get_clocks(dev)) < 0)
234                 return r;
235         if (eac_device != NULL) {
236                 r = n800_register_codec();
237                 if (r < 0) {
238                         n800_codec_put_clocks(dev);
239                         return r;
240                 }
241         }
242         return 0;
243 }
244
245 static void n800_codec_cleanup(struct device *dev)
246 {
247         tsc2301_device = NULL;
248         if (eac_device != NULL)
249                 n800_unregister_codec();
250         n800_codec_put_clocks(dev);
251 }
252
253 static struct eac_platform_data n800_eac_data = {
254         .init = n800_eac_init,
255         .cleanup = n800_eac_cleanup,
256         .enable_ext_clocks = n800_eac_enable_ext_clocks,
257         .disable_ext_clocks = n800_eac_disable_ext_clocks,
258 };
259
260 static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = {
261         {
262                 .name                   = "Headset Amplifier",
263                 .gpio                   = 1,
264                 .deactivate_on_pd       = 1,
265         }, {
266                 .name                   = "Speaker Amplifier",
267                 .gpio                   = 2,
268                 .def_enable             = 1,
269                 .deactivate_on_pd       = 1,
270         }, {
271                 .name                   = "Headset Mic Select",
272                 .gpio                   = 3,
273         }
274 };
275
276 static struct platform_device retu_headset_device = {
277         .name           = "retu-headset",
278         .id             = -1,
279         .dev            = {
280                 .release        = NULL,
281         },
282 };
283
284 void __init n800_audio_init(struct tsc2301_platform_data *tc)
285 {
286         spin_lock_init(&audio_lock);
287
288         if (platform_device_register(&retu_headset_device) < 0)
289                 return;
290         omap_init_eac(&n800_eac_data);
291
292         tc->pll_pdc = 7;
293         tc->pll_a = 7;
294         tc->pll_n = 9;
295         tc->pll_output = 1;
296         tc->mclk_ratio = TSC2301_MCLK_256xFS;
297         tc->i2s_sample_rate = TSC2301_I2S_SR_48000;
298         tc->i2s_format = TSC2301_I2S_FORMAT0;
299         tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD;
300         tc->mixer_gpios = n800_mixer_gpios;
301         tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios);
302         tc->codec_init = n800_codec_init;
303         tc->codec_cleanup = n800_codec_cleanup;
304         tc->enable_clock = n800_codec_enable_clock;
305         tc->disable_clock = n800_codec_disable_clock;
306 }
307
308 #else
309
310 void __init n800_audio_init(void)
311 {
312 }
313
314 #endif
315
316 #ifdef CONFIG_OMAP_DSP
317
318 int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage)
319 {
320 #ifdef AUDIO_ENABLED
321         unsigned long flags;
322         int do_enable = 0;
323
324         spin_lock_irqsave(&audio_lock, flags);
325
326         pr_debug("DSP power up request (audio codec %sinitialized)\n",
327                  audio_ok ? "" : "not ");
328
329         if (enable_audio)
330                 goto out;
331         enable_audio = 1;
332         if (audio_ok)
333                 do_enable = 1;
334 out:
335         spin_unlock_irqrestore(&audio_lock, flags);
336         if (do_enable)
337                 eac_set_mode(eac_device, 1, 1);
338 #endif
339         return 0;
340 }
341
342 int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage)
343 {
344 #ifdef AUDIO_ENABLED
345         unsigned long flags;
346         int do_disable = 0;
347
348         spin_lock_irqsave(&audio_lock, flags);
349
350         pr_debug("DSP power down request (audio codec %sinitialized)\n",
351                 audio_ok ? "" : "not ");
352
353         if (!enable_audio)
354                 goto out;
355         enable_audio = 0;
356         if (audio_ok)
357                 do_disable = 1;
358 out:
359         spin_unlock_irqrestore(&audio_lock, flags);
360         if (do_disable)
361                 eac_set_mode(eac_device, 0, 0);
362 #endif
363         return 0;
364 }
365
366 #endif /* CONFIG_OMAP_DSP */