]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-tsc2101.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / sound / arm / omap / omap-alsa-tsc2101.c
1 /*
2  * sound/arm/omap/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
38 #include <asm/arch/omap-alsa.h>
39 #include "omap-alsa-tsc2101.h"
40
41 static struct clk *tsc2101_mclk = 0;
42
43 //#define DUMP_TSC2101_AUDIO_REGISTERS
44 #undef DUMP_TSC2101_AUDIO_REGISTERS
45
46 /*
47  * Hardware capabilities 
48  */
49
50 /*
51  * DAC USB-mode sampling rates (MCLK = 12 MHz)
52  * The rates and rate_reg_into MUST be in the same order
53  */
54 static unsigned int rates[] = {
55         7350, 8000, 8018, 8727,
56         8820, 9600, 11025, 12000,
57         14700, 16000, 22050, 24000,
58         29400, 32000, 44100, 48000,
59 };
60
61 static struct snd_pcm_hw_constraint_list tsc2101_hw_constraints_rates = {
62         .count = ARRAY_SIZE(rates),
63         .list = rates,
64         .mask = 0,
65 };
66
67 static const struct tsc2101_samplerate_reg_info
68     rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
69         /* Div 6 */
70         {7350, 7, 1},
71         {8000, 7, 0},
72         /* Div 5.5 */
73         {8018, 6, 1},
74         {8727, 6, 0},
75         /* Div 5 */
76         {8820, 5, 1},
77         {9600, 5, 0},   
78         /* Div 4 */
79         {11025, 4, 1},
80         {12000, 4, 0},
81         /* Div 3 */
82         {14700, 3, 1},
83         {16000, 3, 0},
84         /* Div 2 */
85         {22050, 2, 1},
86         {24000, 2, 0},
87         /* Div 1.5 */
88         {29400, 1, 1},
89         {32000, 1, 0},
90         /* Div 1 */
91         {44100, 0, 1},
92         {48000, 0, 0},          
93 };
94
95 static struct snd_pcm_hardware tsc2101_snd_omap_alsa_playback = {
96         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
97                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
98 #ifdef CONFIG_MACH_OMAP_H6300
99         .formats = (SNDRV_PCM_FMTBIT_S8),
100 #else
101         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
102 #endif
103         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
104                   SNDRV_PCM_RATE_16000 |
105                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
106                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
107                   SNDRV_PCM_RATE_KNOT),
108         .rate_min = 7350,
109         .rate_max = 48000,
110         .channels_min = 2,
111         .channels_max = 2,
112         .buffer_bytes_max = 128 * 1024,
113         .period_bytes_min = 32,
114         .period_bytes_max = 8 * 1024,
115         .periods_min = 16,
116         .periods_max = 255,
117         .fifo_size = 0,
118 };
119
120 static struct snd_pcm_hardware tsc2101_snd_omap_alsa_capture = {
121         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
122                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
123         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
124         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
125                   SNDRV_PCM_RATE_16000 |
126                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
127                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
128                   SNDRV_PCM_RATE_KNOT),
129         .rate_min = 7350,
130         .rate_max = 48000,
131         .channels_min = 2,
132         .channels_max = 2,
133         .buffer_bytes_max = 128 * 1024,
134         .period_bytes_min = 32,
135         .period_bytes_max = 8 * 1024,
136         .periods_min = 16,
137         .periods_max = 255,
138         .fifo_size = 0,
139 };
140
141 /* 
142  * Simplified write for tsc2101 audio registers.
143  */
144 inline void tsc2101_audio_write(u8 address, u16 data)
145 {
146         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
147 }
148
149 /* 
150  * Simplified read for tsc2101 audio registers.
151  */
152 inline u16 tsc2101_audio_read(u8 address)
153 {
154         return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
155 }
156
157 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
158 void dump_tsc2101_audio_reg(void) {
159         printk("TSC2101_AUDIO_CTRL_1 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_1));
160         printk("TSC2101_HEADSET_GAIN_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL));
161         printk("TSC2101_DAC_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL));
162         printk("TSC2101_MIXER_PGA_CTRL = 0x%04x\n",     tsc2101_audio_read(TSC2101_MIXER_PGA_CTRL));
163         printk("TSC2101_AUDIO_CTRL_2 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_2));
164         printk("TSC2101_CODEC_POWER_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_CODEC_POWER_CTRL));
165         printk("TSC2101_AUDIO_CTRL_3 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_3));
166         printk("TSC2101_LCH_BASS_BOOST_N0 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N0));
167         printk("TSC2101_LCH_BASS_BOOST_N1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N1));
168         printk("TSC2101_LCH_BASS_BOOST_N2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N2));
169         printk("TSC2101_LCH_BASS_BOOST_N3 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N3));
170         printk("TSC2101_LCH_BASS_BOOST_N4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N4));
171         printk("TSC2101_LCH_BASS_BOOST_N5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N5));
172         printk("TSC2101_LCH_BASS_BOOST_D1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D1));
173         printk("TSC2101_LCH_BASS_BOOST_D2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D2));
174         printk("TSC2101_LCH_BASS_BOOST_D4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D4));
175         printk("TSC2101_LCH_BASS_BOOST_D5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D5));
176         
177         printk("TSC2101_RCH_BASS_BOOST_N0 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N0));
178         printk("TSC2101_RCH_BASS_BOOST_N1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N1));
179         printk("TSC2101_RCH_BASS_BOOST_N2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N2));
180         printk("TSC2101_RCH_BASS_BOOST_N3 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N3));
181         printk("TSC2101_RCH_BASS_BOOST_N4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N4));
182         printk("TSC2101_RCH_BASS_BOOST_N5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N5));
183         printk("TSC2101_RCH_BASS_BOOST_D1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D1));
184         printk("TSC2101_RCH_BASS_BOOST_D2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D2));
185         printk("TSC2101_RCH_BASS_BOOST_D4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D4));
186         printk("TSC2101_RCH_BASS_BOOST_D5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D5));
187                                         
188         printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_1));
189         printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_2));
190         printk("TSC2101_AUDIO_CTRL_4 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
191         printk("TSC2101_HANDSET_GAIN_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL));
192         printk("TSC2101_BUZZER_GAIN_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL));
193         printk("TSC2101_AUDIO_CTRL_5 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_5));
194         printk("TSC2101_AUDIO_CTRL_6 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_6));
195         printk("TSC2101_AUDIO_CTRL_7 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_7));
196         printk("TSC2101_GPIO_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_GPIO_CTRL));
197         printk("TSC2101_AGC_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_AGC_CTRL));
198         printk("TSC2101_POWERDOWN_STS = 0x%04x\n",      tsc2101_audio_read(TSC2101_POWERDOWN_STS));
199         printk("TSC2101_MIC_AGC_CONTROL = 0x%04x\n",    tsc2101_audio_read(TSC2101_MIC_AGC_CONTROL));
200         printk("TSC2101_CELL_AGC_CONTROL = 0x%04x\n",   tsc2101_audio_read(TSC2101_CELL_AGC_CONTROL));
201 }
202 #endif
203
204 /*
205  * ALSA operations according to board file
206  */
207
208 /*
209  * Sample rate changing
210  */
211 void tsc2101_set_samplerate(long sample_rate)
212 {
213         u8 count = 0;
214         u16 data = 0;
215         int clkgdv = 0;
216
217         u16 srgr1, srgr2;
218         /* wait for any frame to complete */
219         udelay(125);
220         ADEBUG();
221
222         sample_rate     = sample_rate;
223         /* Search for the right sample rate */
224         while ((rate_reg_info[count].sample_rate != sample_rate) &&
225                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
226                 count++;
227         }
228         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
229                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
230                        (int) sample_rate);
231                 return;         // -EPERM;
232         }
233
234         /* Set AC1 */
235         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1);
236         /* Clear prev settings */
237         data    &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
238         data    |= AC1_DACFS(rate_reg_info[count].divisor) | 
239                         AC1_ADCFS(rate_reg_info[count].divisor);
240         tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data);
241
242         /* Set the AC3 */
243         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3);
244         /*Clear prev settings */
245         data    &= ~(AC3_REFFS | AC3_SLVMS);
246         data    |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
247 #ifdef TSC_MASTER
248         data    |= AC3_SLVMS;
249 #endif                          /* #ifdef TSC_MASTER */
250         tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
251
252         /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
253          * If MCLK rate is something else, these values must be changed.
254          * See the tsc2101 specification for the details.
255          */
256         if (rate_reg_info[count].fs_44kHz) {
257                 /* samplerate = (44.1kHZ / x), where x is int. */
258                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
259                                 PLL1_PVAL(1) | PLL1_I_VAL(7));  /* PVAL 1; I_VAL 7 */
260                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
261         } else {
262                 /* samplerate = (48.kHZ / x), where x is int. */
263                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
264                                PLL1_PVAL(1) | PLL1_I_VAL(8));   /* PVAL 1; I_VAL 8 */
265                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
266         }
267
268         /* Set the sample rate */
269 #ifndef TSC_MASTER
270         clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
271         if (clkgdv)
272                 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
273         else
274                 return (1);
275
276         /* Stereo Mode */
277         srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
278 #else
279         srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
280         srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
281
282 #endif                          /* end of #ifdef TSC_MASTER */
283         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2);
284         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1);
285 }
286
287 void tsc2101_configure(void)
288 {
289 }
290
291 /*
292  *  Omap MCBSP clock and Power Management configuration
293  *  
294  *  Here we have some functions that allows clock to be enabled and
295  *   disabled only when needed. Besides doing clock configuration 
296  *   it allows turn on/turn off audio when necessary. 
297  */
298  
299 /*
300  * Do clock framework mclk search
301  */
302 void tsc2101_clock_setup(void)
303 {
304         tsc2101_mclk = clk_get(0, "mclk");
305 }
306
307 /*
308  * Do some sanity check, set clock rate, starts it and turn codec audio on
309  */
310 int tsc2101_clock_on(void) 
311 {
312         int     curUseCount;
313         uint    curRate;
314         int     err;
315
316         curUseCount     = clk_get_usecount(tsc2101_mclk);
317         DPRINTK("clock use count = %d\n", curUseCount);
318         if (curUseCount > 0) {
319                 // MCLK is already in use
320                 printk(KERN_WARNING
321                        "MCLK already in use at %d Hz. We change it to %d Hz\n",
322                        (uint) clk_get_rate(tsc2101_mclk),
323                        CODEC_CLOCK);
324         }
325         curRate = (uint)clk_get_rate(tsc2101_mclk);
326         if (curRate != CODEC_CLOCK) {
327                 err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
328                 if (err) {
329                         printk(KERN_WARNING
330                                "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
331                         return -ECANCELED;
332                 }
333         }
334         err             = clk_enable(tsc2101_mclk);
335         curRate         = (uint)clk_get_rate(tsc2101_mclk);
336         curUseCount     = clk_get_usecount(tsc2101_mclk);
337         DPRINTK("MCLK = %d [%d], usecount = %d, clk_enable retval = %d\n",
338                curRate, 
339                CODEC_CLOCK,
340                curUseCount,
341                err);
342
343         // Now turn the audio on
344         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS,
345                         TSC2101_CODEC_POWER_CTRL,
346                         0x0000);        
347         return 0;       
348 }
349
350 /*
351  * Do some sanity check, turn clock off and then turn codec audio off
352  */
353 int tsc2101_clock_off(void) 
354 {
355         int curUseCount;
356         int curRate;
357
358         curUseCount     = clk_get_usecount(tsc2101_mclk);
359         DPRINTK("clock use count = %d\n", curUseCount);
360         if  (curUseCount > 0) {
361                 curRate = clk_get_rate(tsc2101_mclk);
362                 DPRINTK("clock rate = %d\n", curRate);
363                 if (curRate != CODEC_CLOCK) {
364                         printk(KERN_WARNING
365                                "MCLK for audio should be %d Hz. But is %d Hz\n",
366                                (uint) clk_get_rate(tsc2101_mclk),
367                                CODEC_CLOCK);
368                 }
369                 clk_disable(tsc2101_mclk);
370                 DPRINTK("clock disabled\n");
371         }
372         tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
373                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
374         DPRINTK("audio codec off\n");
375         return 0;       
376 }
377
378 int tsc2101_get_default_samplerate(void)
379 {
380         return DEFAULT_SAMPLE_RATE;
381 }
382
383 static int __devinit snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
384 {
385         int     ret;
386         struct  omap_alsa_codec_config *codec_cfg;
387         
388         codec_cfg = pdev->dev.platform_data;
389         if (codec_cfg != NULL) {
390                 codec_cfg->hw_constraints_rates = &tsc2101_hw_constraints_rates;
391                 codec_cfg->snd_omap_alsa_playback  = &tsc2101_snd_omap_alsa_playback;
392                 codec_cfg->snd_omap_alsa_capture  = &tsc2101_snd_omap_alsa_capture;
393                 codec_cfg->codec_configure_dev  = tsc2101_configure;
394                 codec_cfg->codec_set_samplerate = tsc2101_set_samplerate;
395                 codec_cfg->codec_clock_setup    = tsc2101_clock_setup;
396                 codec_cfg->codec_clock_on       = tsc2101_clock_on;
397                 codec_cfg->codec_clock_off      = tsc2101_clock_off;
398                 codec_cfg->get_default_samplerate = tsc2101_get_default_samplerate;
399                 ret     = snd_omap_alsa_post_probe(pdev, codec_cfg);
400         }
401         else
402                 ret = -ENODEV;
403         return ret;
404 }
405
406 static struct platform_driver omap_alsa_driver = {
407         .probe          = snd_omap_alsa_tsc2101_probe,
408         .remove         = snd_omap_alsa_remove,
409         .suspend        = snd_omap_alsa_suspend,
410         .resume         = snd_omap_alsa_resume,
411         .driver = {
412                 .name = "omap_alsa_mcbsp",
413         },
414 };
415
416 static int __init omap_alsa_tsc2101_init(void)
417 {       
418         ADEBUG();
419 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
420         printk("omap_alsa_tsc2101_init()\n");
421         dump_tsc2101_audio_reg();
422 #endif
423         return platform_driver_register(&omap_alsa_driver);
424 }
425
426 static void __exit omap_alsa_tsc2101_exit(void)
427 {
428         ADEBUG();
429 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
430         printk("omap_alsa_tsc2101_exit()\n");
431         dump_tsc2101_audio_reg();
432 #endif
433         platform_driver_unregister(&omap_alsa_driver);
434 }
435
436 module_init(omap_alsa_tsc2101_init);
437 module_exit(omap_alsa_tsc2101_exit);