]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-tsc2101.c
h63xx: tsc2101 alsa sound support
[linux-2.6-omap-h63xx.git] / sound / arm / omap / omap-alsa-tsc2101.c
1 /*
2  * arch/arm/mach-omap1/omap-alsa-tsc2101.c
3  * 
4  * Alsa codec Driver for TSC2101 chip for OMAP platform boards. 
5  * Code obtained from oss omap drivers
6  *
7  * Copyright (C) 2004 Texas Instruments, Inc.
8  *      Written by Nishanth Menon and Sriram Kannan
9  *      
10  * Copyright (C) 2006 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
11  *      Alsa modularization by Daniel Petrini (d.pensator@gmail.com)
12  * 
13  * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
14  *
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.
19  */
20
21 #include <linux/delay.h>
22 #include <linux/soundcard.h>
23 #include <linux/platform_device.h>
24 #include <linux/clk.h>
25 #include <asm/io.h>
26 #include <asm/arch/mcbsp.h>
27
28 #include <linux/slab.h>
29 #ifdef CONFIG_PM
30 #include <linux/pm.h>
31 #endif
32 #include <asm/mach-types.h>
33 #include <asm/arch/dma.h>
34 #include <asm/arch/clock.h>
35
36 #include <asm/hardware/tsc2101.h>
37 #include <../drivers/ssi/omap-tsc2101.h>
38
39 #include <asm/arch/omap-alsa.h>
40 #include "omap-alsa-tsc2101.h"
41
42 static struct clk *tsc2101_mclk = 0;
43
44 //#define DUMP_TSC2101_AUDIO_REGISTERS
45 #undef DUMP_TSC2101_AUDIO_REGISTERS
46
47 /*
48  * Hardware capabilities 
49  */
50
51 /*
52  * DAC USB-mode sampling rates (MCLK = 12 MHz)
53  * The rates and rate_reg_into MUST be in the same order
54  */
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,
60 };
61
62 static snd_pcm_hw_constraint_list_t tsc2101_hw_constraints_rates = {
63         .count = ARRAY_SIZE(rates),
64         .list = rates,
65         .mask = 0,
66 };
67
68 static const struct tsc2101_samplerate_reg_info
69     rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
70         /* Div 6 */
71         {7350, 7, 1},
72         {8000, 7, 0},
73         /* Div 5.5 */
74         {8018, 6, 1},
75         {8727, 6, 0},
76         /* Div 5 */
77         {8820, 5, 1},
78         {9600, 5, 0},   
79         /* Div 4 */
80         {11025, 4, 1},
81         {12000, 4, 0},
82         /* Div 3 */
83         {14700, 3, 1},
84         {16000, 3, 0},
85         /* Div 2 */
86         {22050, 2, 1},
87         {24000, 2, 0},
88         /* Div 1.5 */
89         {29400, 1, 1},
90         {32000, 1, 0},
91         /* Div 1 */
92         {44100, 0, 1},
93         {48000, 0, 0},          
94 };
95
96 static snd_pcm_hardware_t 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),
101 #else
102         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
103 #endif
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),
109         .rate_min = 7350,
110         .rate_max = 48000,
111         .channels_min = 2,
112         .channels_max = 2,
113         .buffer_bytes_max = 128 * 1024,
114         .period_bytes_min = 32,
115         .period_bytes_max = 8 * 1024,
116         .periods_min = 16,
117         .periods_max = 255,
118         .fifo_size = 0,
119 };
120
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),
130         .rate_min = 7350,
131         .rate_max = 48000,
132         .channels_min = 2,
133         .channels_max = 2,
134         .buffer_bytes_max = 128 * 1024,
135         .period_bytes_min = 32,
136         .period_bytes_max = 8 * 1024,
137         .periods_min = 16,
138         .periods_max = 255,
139         .fifo_size = 0,
140 };
141
142 /* 
143  * Simplified write for tsc2101 audio registers.
144  */
145 inline void tsc2101_audio_write(u8 address, u16 data)
146 {
147         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
148 }
149
150 /* 
151  * Simplified read for tsc2101 audio registers.
152  */
153 inline u16 tsc2101_audio_read(u8 address)
154 {
155         return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
156 }
157
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));
177         
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));
188                                         
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));
202 }
203 #endif
204
205 /*
206  * ALSA operations according to board file
207  */
208
209 /*
210  * Sample rate changing
211  */
212 void tsc2101_set_samplerate(long sample_rate)
213 {
214         u8 count = 0;
215         u16 data = 0;
216         int clkgdv = 0;
217
218         u16 srgr1, srgr2;
219         /* wait for any frame to complete */
220         udelay(125);
221         ADEBUG();
222
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)) {
227                 count++;
228         }
229         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
230                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
231                        (int) sample_rate);
232                 return;         // -EPERM;
233         }
234
235         /* Set AC1 */
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);
242
243         /* Set the AC3 */
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;
248 #ifdef TSC_MASTER
249         data    |= AC3_SLVMS;
250 #endif                          /* #ifdef TSC_MASTER */
251         tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
252
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.
256          */
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 */
262         } else {
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 */
267         }
268
269         /* Set the sample rate */
270 #ifndef TSC_MASTER
271         clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
272         if (clkgdv)
273                 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
274         else
275                 return (1);
276
277         /* Stereo Mode */
278         srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
279 #else
280         srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
281         srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
282
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);
286 }
287
288 void tsc2101_configure(void)
289 {
290 }
291
292 /*
293  *  Omap MCBSP clock and Power Management configuration
294  *  
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. 
298  */
299  
300 /*
301  * Do clock framework mclk search
302  */
303 void tsc2101_clock_setup(void)
304 {
305         tsc2101_mclk = clk_get(0, "mclk");
306 }
307
308 /*
309  * Do some sanity check, set clock rate, starts it and turn codec audio on
310  */
311 int tsc2101_clock_on(void) 
312 {
313         int     curUseCount;
314         uint    curRate;
315         int     err;
316
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
321                 printk(KERN_WARNING
322                        "MCLK already in use at %d Hz. We change it to %d Hz\n",
323                        (uint) clk_get_rate(tsc2101_mclk),
324                        CODEC_CLOCK);
325         }
326         curRate = (uint)clk_get_rate(tsc2101_mclk);
327         if (curRate != CODEC_CLOCK) {
328                 err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
329                 if (err) {
330                         printk(KERN_WARNING
331                                "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
332                         return -ECANCELED;
333                 }
334         }
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",
339                curRate, 
340                CODEC_CLOCK,
341                curUseCount,
342                err);
343
344         // Now turn the audio on
345         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS,
346                         TSC2101_CODEC_POWER_CTRL,
347                         0x0000);        
348         return 0;       
349 }
350
351 /*
352  * Do some sanity check, turn clock off and then turn codec audio off
353  */
354 int tsc2101_clock_off(void) 
355 {
356         int curUseCount;
357         int curRate;
358
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) {
365                         printk(KERN_WARNING
366                                "MCLK for audio should be %d Hz. But is %d Hz\n",
367                                (uint) clk_get_rate(tsc2101_mclk),
368                                CODEC_CLOCK);
369                 }
370                 clk_disable(tsc2101_mclk);
371                 DPRINTK("clock disabled\n");
372         }
373         tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
374                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
375         DPRINTK("audio codec off\n");
376         return 0;       
377 }
378
379 int tsc2101_get_default_samplerate(void)
380 {
381         return DEFAULT_SAMPLE_RATE;
382 }
383
384 static int __init snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
385 {
386         int     ret;
387         struct  omap_alsa_codec_config *codec_cfg;
388         
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);
401         }
402         else
403                 ret = -ENODEV;
404         return ret;
405 }
406
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,
412         .driver = {
413                 .name = "omap_alsa_mcbsp",
414         },
415 };
416
417 static int __init omap_alsa_tsc2101_init(void)
418 {       
419         ADEBUG();
420 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
421         printk("omap_alsa_tsc2101_init()\n");
422         dump_tsc2101_audio_reg();
423 #endif
424         return platform_driver_register(&omap_alsa_driver);
425 }
426
427 static void __exit omap_alsa_tsc2101_exit(void)
428 {
429         ADEBUG();
430 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
431         printk("omap_alsa_tsc2101_exit()\n");
432         dump_tsc2101_audio_reg();
433 #endif
434         platform_driver_unregister(&omap_alsa_driver);
435 }
436
437 module_init(omap_alsa_tsc2101_init);
438 module_exit(omap_alsa_tsc2101_exit);