2 * sound/arm/omap/omap-alsa-tsc2101.c
4 * Alsa codec Driver for TSC2101 chip for OMAP platform boards.
5 * Code obtained from oss omap drivers
7 * Copyright (C) 2004 Texas Instruments, Inc.
8 * Written by Nishanth Menon and Sriram Kannan
10 * Copyright (C) 2006 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
11 * Alsa modularization by Daniel Petrini (d.pensator@gmail.com)
13 * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version.
21 #include <linux/delay.h>
22 #include <linux/soundcard.h>
23 #include <linux/platform_device.h>
24 #include <linux/clk.h>
26 #include <asm/arch/mcbsp.h>
28 #include <linux/slab.h>
32 #include <asm/mach-types.h>
33 #include <asm/arch/dma.h>
34 #include <asm/arch/clock.h>
36 #include <asm/hardware/tsc2101.h>
37 #include <../drivers/ssi/omap-tsc2101.h>
39 #include <asm/arch/omap-alsa.h>
40 #include "omap-alsa-tsc2101.h"
42 static struct clk *tsc2101_mclk = 0;
44 //#define DUMP_TSC2101_AUDIO_REGISTERS
45 #undef DUMP_TSC2101_AUDIO_REGISTERS
48 * Hardware capabilities
52 * DAC USB-mode sampling rates (MCLK = 12 MHz)
53 * The rates and rate_reg_into MUST be in the same order
55 static unsigned int rates[] = {
56 7350, 8000, 8018, 8727,
57 8820, 9600, 11025, 12000,
58 14700, 16000, 22050, 24000,
59 29400, 32000, 44100, 48000,
62 static struct snd_pcm_hw_constraint_list tsc2101_hw_constraints_rates = {
63 .count = ARRAY_SIZE(rates),
68 static const struct tsc2101_samplerate_reg_info
69 rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
96 static struct snd_pcm_hardware tsc2101_snd_omap_alsa_playback = {
97 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
98 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
99 #ifdef CONFIG_MACH_OMAP_H6300
100 .formats = (SNDRV_PCM_FMTBIT_S8),
102 .formats = (SNDRV_PCM_FMTBIT_S16_LE),
104 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
105 SNDRV_PCM_RATE_16000 |
106 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
107 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
108 SNDRV_PCM_RATE_KNOT),
113 .buffer_bytes_max = 128 * 1024,
114 .period_bytes_min = 32,
115 .period_bytes_max = 8 * 1024,
121 static snd_pcm_hardware_t tsc2101_snd_omap_alsa_capture = {
122 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
123 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
124 .formats = (SNDRV_PCM_FMTBIT_S16_LE),
125 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
126 SNDRV_PCM_RATE_16000 |
127 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
128 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
129 SNDRV_PCM_RATE_KNOT),
134 .buffer_bytes_max = 128 * 1024,
135 .period_bytes_min = 32,
136 .period_bytes_max = 8 * 1024,
143 * Simplified write for tsc2101 audio registers.
145 inline void tsc2101_audio_write(u8 address, u16 data)
147 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
151 * Simplified read for tsc2101 audio registers.
153 inline u16 tsc2101_audio_read(u8 address)
155 return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
158 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
159 void dump_tsc2101_audio_reg(void) {
160 printk("TSC2101_AUDIO_CTRL_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_1));
161 printk("TSC2101_HEADSET_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL));
162 printk("TSC2101_DAC_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL));
163 printk("TSC2101_MIXER_PGA_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_MIXER_PGA_CTRL));
164 printk("TSC2101_AUDIO_CTRL_2 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_2));
165 printk("TSC2101_CODEC_POWER_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_CODEC_POWER_CTRL));
166 printk("TSC2101_AUDIO_CTRL_3 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_3));
167 printk("TSC2101_LCH_BASS_BOOST_N0 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N0));
168 printk("TSC2101_LCH_BASS_BOOST_N1 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N1));
169 printk("TSC2101_LCH_BASS_BOOST_N2 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N2));
170 printk("TSC2101_LCH_BASS_BOOST_N3 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N3));
171 printk("TSC2101_LCH_BASS_BOOST_N4 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N4));
172 printk("TSC2101_LCH_BASS_BOOST_N5 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N5));
173 printk("TSC2101_LCH_BASS_BOOST_D1 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D1));
174 printk("TSC2101_LCH_BASS_BOOST_D2 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D2));
175 printk("TSC2101_LCH_BASS_BOOST_D4 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D4));
176 printk("TSC2101_LCH_BASS_BOOST_D5 = 0x%04x\n", tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D5));
178 printk("TSC2101_RCH_BASS_BOOST_N0 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N0));
179 printk("TSC2101_RCH_BASS_BOOST_N1 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N1));
180 printk("TSC2101_RCH_BASS_BOOST_N2 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N2));
181 printk("TSC2101_RCH_BASS_BOOST_N3 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N3));
182 printk("TSC2101_RCH_BASS_BOOST_N4 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N4));
183 printk("TSC2101_RCH_BASS_BOOST_N5 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N5));
184 printk("TSC2101_RCH_BASS_BOOST_D1 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D1));
185 printk("TSC2101_RCH_BASS_BOOST_D2 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D2));
186 printk("TSC2101_RCH_BASS_BOOST_D4 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D4));
187 printk("TSC2101_RCH_BASS_BOOST_D5 = 0x%04x\n", tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D5));
189 printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_1));
190 printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_2));
191 printk("TSC2101_AUDIO_CTRL_4 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
192 printk("TSC2101_HANDSET_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL));
193 printk("TSC2101_BUZZER_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL));
194 printk("TSC2101_AUDIO_CTRL_5 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_5));
195 printk("TSC2101_AUDIO_CTRL_6 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_6));
196 printk("TSC2101_AUDIO_CTRL_7 = 0x%04x\n", tsc2101_audio_read(TSC2101_AUDIO_CTRL_7));
197 printk("TSC2101_GPIO_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_GPIO_CTRL));
198 printk("TSC2101_AGC_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_AGC_CTRL));
199 printk("TSC2101_POWERDOWN_STS = 0x%04x\n", tsc2101_audio_read(TSC2101_POWERDOWN_STS));
200 printk("TSC2101_MIC_AGC_CONTROL = 0x%04x\n", tsc2101_audio_read(TSC2101_MIC_AGC_CONTROL));
201 printk("TSC2101_CELL_AGC_CONTROL = 0x%04x\n", tsc2101_audio_read(TSC2101_CELL_AGC_CONTROL));
206 * ALSA operations according to board file
210 * Sample rate changing
212 void tsc2101_set_samplerate(long sample_rate)
219 /* wait for any frame to complete */
223 sample_rate = sample_rate;
224 /* Search for the right sample rate */
225 while ((rate_reg_info[count].sample_rate != sample_rate) &&
226 (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
229 if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
230 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
236 data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1);
237 /* Clear prev settings */
238 data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
239 data |= AC1_DACFS(rate_reg_info[count].divisor) |
240 AC1_ADCFS(rate_reg_info[count].divisor);
241 tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data);
244 data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3);
245 /*Clear prev settings */
246 data &= ~(AC3_REFFS | AC3_SLVMS);
247 data |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
250 #endif /* #ifdef TSC_MASTER */
251 tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
253 /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
254 * If MCLK rate is something else, these values must be changed.
255 * See the tsc2101 specification for the details.
257 if (rate_reg_info[count].fs_44kHz) {
258 /* samplerate = (44.1kHZ / x), where x is int. */
259 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
260 PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */
261 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */
263 /* samplerate = (48.kHZ / x), where x is int. */
264 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
265 PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */
266 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */
269 /* Set the sample rate */
271 clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
273 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
278 srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
280 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
281 srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
283 #endif /* end of #ifdef TSC_MASTER */
284 OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2);
285 OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1);
288 void tsc2101_configure(void)
293 * Omap MCBSP clock and Power Management configuration
295 * Here we have some functions that allows clock to be enabled and
296 * disabled only when needed. Besides doing clock configuration
297 * it allows turn on/turn off audio when necessary.
301 * Do clock framework mclk search
303 void tsc2101_clock_setup(void)
305 tsc2101_mclk = clk_get(0, "mclk");
309 * Do some sanity check, set clock rate, starts it and turn codec audio on
311 int tsc2101_clock_on(void)
317 curUseCount = clk_get_usecount(tsc2101_mclk);
318 DPRINTK("clock use count = %d\n", curUseCount);
319 if (curUseCount > 0) {
320 // MCLK is already in use
322 "MCLK already in use at %d Hz. We change it to %d Hz\n",
323 (uint) clk_get_rate(tsc2101_mclk),
326 curRate = (uint)clk_get_rate(tsc2101_mclk);
327 if (curRate != CODEC_CLOCK) {
328 err = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
331 "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
335 err = clk_enable(tsc2101_mclk);
336 curRate = (uint)clk_get_rate(tsc2101_mclk);
337 curUseCount = clk_get_usecount(tsc2101_mclk);
338 DPRINTK("MCLK = %d [%d], usecount = %d, clk_enable retval = %d\n",
344 // Now turn the audio on
345 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS,
346 TSC2101_CODEC_POWER_CTRL,
352 * Do some sanity check, turn clock off and then turn codec audio off
354 int tsc2101_clock_off(void)
359 curUseCount = clk_get_usecount(tsc2101_mclk);
360 DPRINTK("clock use count = %d\n", curUseCount);
361 if (curUseCount > 0) {
362 curRate = clk_get_rate(tsc2101_mclk);
363 DPRINTK("clock rate = %d\n", curRate);
364 if (curRate != CODEC_CLOCK) {
366 "MCLK for audio should be %d Hz. But is %d Hz\n",
367 (uint) clk_get_rate(tsc2101_mclk),
370 clk_disable(tsc2101_mclk);
371 DPRINTK("clock disabled\n");
373 tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
374 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
375 DPRINTK("audio codec off\n");
379 int tsc2101_get_default_samplerate(void)
381 return DEFAULT_SAMPLE_RATE;
384 static int __devinit snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
387 struct omap_alsa_codec_config *codec_cfg;
389 codec_cfg = pdev->dev.platform_data;
390 if (codec_cfg != NULL) {
391 codec_cfg->hw_constraints_rates = &tsc2101_hw_constraints_rates;
392 codec_cfg->snd_omap_alsa_playback = &tsc2101_snd_omap_alsa_playback;
393 codec_cfg->snd_omap_alsa_capture = &tsc2101_snd_omap_alsa_capture;
394 codec_cfg->codec_configure_dev = tsc2101_configure;
395 codec_cfg->codec_set_samplerate = tsc2101_set_samplerate;
396 codec_cfg->codec_clock_setup = tsc2101_clock_setup;
397 codec_cfg->codec_clock_on = tsc2101_clock_on;
398 codec_cfg->codec_clock_off = tsc2101_clock_off;
399 codec_cfg->get_default_samplerate = tsc2101_get_default_samplerate;
400 ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
407 static struct platform_driver omap_alsa_driver = {
408 .probe = snd_omap_alsa_tsc2101_probe,
409 .remove = snd_omap_alsa_remove,
410 .suspend = snd_omap_alsa_suspend,
411 .resume = snd_omap_alsa_resume,
413 .name = "omap_alsa_mcbsp",
417 static int __init omap_alsa_tsc2101_init(void)
420 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
421 printk("omap_alsa_tsc2101_init()\n");
422 dump_tsc2101_audio_reg();
424 return platform_driver_register(&omap_alsa_driver);
427 static void __exit omap_alsa_tsc2101_exit(void)
430 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
431 printk("omap_alsa_tsc2101_exit()\n");
432 dump_tsc2101_audio_reg();
434 platform_driver_unregister(&omap_alsa_driver);
437 module_init(omap_alsa_tsc2101_init);
438 module_exit(omap_alsa_tsc2101_exit);