2 * sound/arm/omap/omap-alsa-tsc2102.c
4 * Alsa codec driver for TSC2102 chip for OMAP platforms.
6 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
7 * Code based on the TSC2101 ALSA driver.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
15 #include <linux/delay.h>
16 #include <linux/soundcard.h>
17 #include <linux/platform_device.h>
18 #include <linux/clk.h>
19 #include <linux/module.h>
20 #include <linux/spi/tsc2102.h>
24 #include <asm/arch/dma.h>
25 #include <asm/arch/clock.h>
26 #include <asm/arch/omap-alsa.h>
28 #include "omap-alsa-tsc2102.h"
30 static struct clk *tsc2102_bclk = 0;
33 * Hardware capabilities
36 /* DAC sampling rates (BCLK = 12 MHz) */
37 static unsigned int rates[] = {
38 7350, 8000, 8820, 9600, 11025, 12000, 14700,
39 16000, 22050, 24000, 29400, 32000, 44100, 48000,
42 static struct snd_pcm_hw_constraint_list tsc2102_hw_constraints_rates = {
43 .count = ARRAY_SIZE(rates),
48 static struct snd_pcm_hardware tsc2102_snd_omap_alsa_playback = {
49 .info = SNDRV_PCM_INFO_INTERLEAVED |
50 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
51 SNDRV_PCM_INFO_MMAP_VALID,
52 .formats = SNDRV_PCM_FMTBIT_S16_LE,
53 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
54 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
55 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
56 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_KNOT,
61 .buffer_bytes_max = 128 * 1024,
62 .period_bytes_min = 32,
63 .period_bytes_max = 8 * 1024,
69 #ifdef DUMP_TSC2102_AUDIO_REGISTERS
70 static void dump_tsc2102_audio_regs(void) {
71 printk("TSC2102_AUDIO1_CTRL = 0x%04x\n",
72 tsc2102_read_sync(TSC2102_AUDIO1_CTRL));
73 printk("TSC2102_DAC_GAIN_CTRL = 0x%04x\n",
74 tsc2102_read_sync(TSC2102_DAC_GAIN_CTRL));
75 printk("TSC2102_AUDIO2_CTRL = 0x%04x\n",
76 tsc2102_read_sync(TSC2102_AUDIO2_CTRL));
77 printk("TSC2102_DAC_POWER_CTRL = 0x%04x\n",
78 tsc2102_read_sync(TSC2102_DAC_POWER_CTRL));
79 printk("TSC2102_AUDIO3_CTRL = 0x%04x\n",
80 tsc2102_read_sync(TSC2102_AUDIO_CTRL_3));
81 printk("TSC2102_LCH_BASS_BOOST_N0 = 0x%04x\n",
82 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N0));
83 printk("TSC2102_LCH_BASS_BOOST_N1 = 0x%04x\n",
84 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N1));
85 printk("TSC2102_LCH_BASS_BOOST_N2 = 0x%04x\n",
86 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N2));
87 printk("TSC2102_LCH_BASS_BOOST_N3 = 0x%04x\n",
88 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N3));
89 printk("TSC2102_LCH_BASS_BOOST_N4 = 0x%04x\n",
90 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N4));
91 printk("TSC2102_LCH_BASS_BOOST_N5 = 0x%04x\n",
92 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_N5));
93 printk("TSC2102_LCH_BASS_BOOST_D1 = 0x%04x\n",
94 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D1));
95 printk("TSC2102_LCH_BASS_BOOST_D2 = 0x%04x\n",
96 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D2));
97 printk("TSC2102_LCH_BASS_BOOST_D4 = 0x%04x\n",
98 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D4));
99 printk("TSC2102_LCH_BASS_BOOST_D5 = 0x%04x\n",
100 tsc2102_read_sync(TSC2102_LCH_BASS_BOOST_D5));
101 printk("TSC2102_RCH_BASS_BOOST_N0 = 0x%04x\n",
102 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N0));
103 printk("TSC2102_RCH_BASS_BOOST_N1 = 0x%04x\n",
104 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N1));
105 printk("TSC2102_RCH_BASS_BOOST_N2 = 0x%04x\n",
106 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N2));
107 printk("TSC2102_RCH_BASS_BOOST_N3 = 0x%04x\n",
108 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N3));
109 printk("TSC2102_RCH_BASS_BOOST_N4 = 0x%04x\n",
110 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N4));
111 printk("TSC2102_RCH_BASS_BOOST_N5 = 0x%04x\n",
112 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_N5));
113 printk("TSC2102_RCH_BASS_BOOST_D1 = 0x%04x\n",
114 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D1));
115 printk("TSC2102_RCH_BASS_BOOST_D2 = 0x%04x\n",
116 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D2));
117 printk("TSC2102_RCH_BASS_BOOST_D4 = 0x%04x\n",
118 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D4));
119 printk("TSC2102_RCH_BASS_BOOST_D5 = 0x%04x\n",
120 tsc2102_read_sync(TSC2102_RCH_BASS_BOOST_D5));
121 printk("TSC2102_PLL1_CTRL = 0x%04x\n",
122 tsc2102_read_sync(TSC2102_PLL1_CTRL));
123 printk("TSC2102_PLL2_CTRL = 0x%04x\n",
124 tsc2102_read_sync(TSC2102_PLL2_CTRL));
125 printk("TSC2102_AUDIO4_CTRL = 0x%04x\n",
126 tsc2102_read_sync(TSC2102_AUDIO4_CTRL));
131 * ALSA operations according to board file
134 static long current_rate = 0;
137 * Sample rate changing
139 static void tsc2102_set_samplerate(long sample_rate)
144 if (sample_rate == current_rate)
148 if (tsc2102_set_rate(sample_rate))
151 /* Set the sample rate */
153 clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
155 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
160 srgr2 = CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1);
162 srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv);
163 srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1);
165 OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR2, srgr2);
166 OMAP_MCBSP_WRITE(OMAP1510_MCBSP1_BASE, SRGR1, srgr1);
167 current_rate = sample_rate;
170 static void tsc2102_configure(void)
172 tsc2102_dac_power(1);
175 tsc2102_set_i2s_master(1);
177 tsc2102_set_i2s_master(0);
182 * Omap McBSP clock and Power Management configuration
184 * Here we have some functions that allow clock to be enabled and
185 * disabled only when needed. Besides doing clock configuration
186 * they allow turn audio on and off when necessary.
190 * Do clock framework bclk search
192 static void tsc2102_clock_setup(void)
194 tsc2102_bclk = clk_get(0, "bclk");
198 * Do some sanity checks, set clock rate, start it.
200 static int tsc2102_clock_on(void)
204 if (clk_get_usecount(tsc2102_bclk) > 0 &&
205 clk_get_rate(tsc2102_bclk) != CODEC_CLOCK) {
206 /* BCLK is already in use */
208 "BCLK already in use at %d Hz. We change it to %d Hz\n",
209 (uint) clk_get_rate(tsc2102_bclk), CODEC_CLOCK);
211 err = clk_set_rate(tsc2102_bclk, CODEC_CLOCK);
213 printk(KERN_WARNING "Cannot set BCLK clock rate "
214 "for TSC2102 codec, error code = %d\n", err);
217 clk_enable(tsc2102_bclk);
222 * Turn off the audio codec and then stop the clock.
224 static int tsc2102_clock_off(void)
226 DPRINTK("clock use count = %d\n", clk_get_usecount(tsc2102_bclk));
228 clk_disable(tsc2102_bclk);
232 static int tsc2102_get_default_samplerate(void)
234 return DEFAULT_SAMPLE_RATE;
237 static int snd_omap_alsa_tsc2102_suspend(
238 struct platform_device *pdev, pm_message_t state)
240 tsc2102_dac_power(0);
243 return snd_omap_alsa_suspend(pdev, state);
246 static int snd_omap_alsa_tsc2102_resume(struct platform_device *pdev)
248 tsc2102_dac_power(1);
251 tsc2102_set_i2s_master(1);
253 tsc2102_set_i2s_master(0);
256 return snd_omap_alsa_resume(pdev);
259 static int __init snd_omap_alsa_tsc2102_probe(struct platform_device *pdev)
262 struct omap_alsa_codec_config *codec_cfg = pdev->dev.platform_data;
265 codec_cfg->hw_constraints_rates =
266 &tsc2102_hw_constraints_rates;
267 codec_cfg->snd_omap_alsa_playback =
268 &tsc2102_snd_omap_alsa_playback;
269 codec_cfg->codec_configure_dev = tsc2102_configure;
270 codec_cfg->codec_set_samplerate = tsc2102_set_samplerate;
271 codec_cfg->codec_clock_setup = tsc2102_clock_setup;
272 codec_cfg->codec_clock_on = tsc2102_clock_on;
273 codec_cfg->codec_clock_off = tsc2102_clock_off;
274 codec_cfg->get_default_samplerate =
275 tsc2102_get_default_samplerate;
276 ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
283 static int snd_omap_alsa_tsc2102_remove(struct platform_device *pdev)
285 tsc2102_dac_power(0);
287 return snd_omap_alsa_remove(pdev);
290 static struct platform_driver omap_alsa_driver = {
291 .probe = snd_omap_alsa_tsc2102_probe,
292 .remove = snd_omap_alsa_tsc2102_remove,
293 .suspend = snd_omap_alsa_tsc2102_suspend,
294 .resume = snd_omap_alsa_tsc2102_resume,
296 .name = "tsc2102-alsa",
297 .owner = THIS_MODULE,
301 static int __init omap_alsa_tsc2102_init(void)
306 err = platform_driver_register(&omap_alsa_driver);
311 static void __exit omap_alsa_tsc2102_exit(void)
314 platform_driver_unregister(&omap_alsa_driver);
317 module_init(omap_alsa_tsc2102_init);
318 module_exit(omap_alsa_tsc2102_exit);