]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-tsc2101.c
a0096cb62fce5c8beee1c63dd8baa2ba4039529a
[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         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
100         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
101                   SNDRV_PCM_RATE_16000 |
102                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
103                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
104                   SNDRV_PCM_RATE_KNOT),
105         .rate_min = 7350,
106         .rate_max = 48000,
107         .channels_min = 2,
108         .channels_max = 2,
109         .buffer_bytes_max = 128 * 1024,
110         .period_bytes_min = 32,
111         .period_bytes_max = 8 * 1024,
112         .periods_min = 16,
113         .periods_max = 255,
114         .fifo_size = 0,
115 };
116
117 static snd_pcm_hardware_t tsc2101_snd_omap_alsa_capture = {
118         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
119                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
120         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
121         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
122                   SNDRV_PCM_RATE_16000 |
123                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
124                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
125                   SNDRV_PCM_RATE_KNOT),
126         .rate_min = 7350,
127         .rate_max = 48000,
128         .channels_min = 2,
129         .channels_max = 2,
130         .buffer_bytes_max = 128 * 1024,
131         .period_bytes_min = 32,
132         .period_bytes_max = 8 * 1024,
133         .periods_min = 16,
134         .periods_max = 255,
135         .fifo_size = 0,
136 };
137
138 /* 
139  * Simplified write for tsc Audio
140  */
141 inline void tsc2101_audio_write(u8 address, u16 data)
142 {
143         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
144 }
145
146 /* 
147  * Simplified read for tsc  Audio
148  */
149 inline u16 tsc2101_audio_read(u8 address)
150 {
151         return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
152 }
153
154 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
155 void dump_tsc2101_audio_reg(void) {
156         printk("TSC2101_AUDIO_CTRL_1 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_1));
157         printk("TSC2101_HEADSET_GAIN_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL));
158         printk("TSC2101_DAC_GAIN_CTRL = 0x%04x\n", tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL));
159         printk("TSC2101_MIXER_PGA_CTRL = 0x%04x\n",     tsc2101_audio_read(TSC2101_MIXER_PGA_CTRL));
160         printk("TSC2101_AUDIO_CTRL_2 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_2));
161         printk("TSC2101_CODEC_POWER_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_CODEC_POWER_CTRL));
162         printk("TSC2101_AUDIO_CTRL_3 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_3));
163         printk("TSC2101_LCH_BASS_BOOST_N0 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N0));
164         printk("TSC2101_LCH_BASS_BOOST_N1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N1));
165         printk("TSC2101_LCH_BASS_BOOST_N2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N2));
166         printk("TSC2101_LCH_BASS_BOOST_N3 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N3));
167         printk("TSC2101_LCH_BASS_BOOST_N4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N4));
168         printk("TSC2101_LCH_BASS_BOOST_N5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N5));
169         printk("TSC2101_LCH_BASS_BOOST_D1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D1));
170         printk("TSC2101_LCH_BASS_BOOST_D2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D2));
171         printk("TSC2101_LCH_BASS_BOOST_D4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D4));
172         printk("TSC2101_LCH_BASS_BOOST_D5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D5));
173         
174         printk("TSC2101_RCH_BASS_BOOST_N0 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N0));
175         printk("TSC2101_RCH_BASS_BOOST_N1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N1));
176         printk("TSC2101_RCH_BASS_BOOST_N2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N2));
177         printk("TSC2101_RCH_BASS_BOOST_N3 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N3));
178         printk("TSC2101_RCH_BASS_BOOST_N4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N4));
179         printk("TSC2101_RCH_BASS_BOOST_N5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N5));
180         printk("TSC2101_RCH_BASS_BOOST_D1 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D1));
181         printk("TSC2101_RCH_BASS_BOOST_D2 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D2));
182         printk("TSC2101_RCH_BASS_BOOST_D4 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D4));
183         printk("TSC2101_RCH_BASS_BOOST_D5 = 0x%04x\n",  tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D5));
184                                         
185         printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_1));
186         printk("TSC2101_PLL_PROG_1 = 0x%04x\n", tsc2101_audio_read(TSC2101_PLL_PROG_2));
187         printk("TSC2101_AUDIO_CTRL_4 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
188         printk("TSC2101_HANDSET_GAIN_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL));
189         printk("TSC2101_BUZZER_GAIN_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL));
190         printk("TSC2101_AUDIO_CTRL_5 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_5));
191         printk("TSC2101_AUDIO_CTRL_6 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_6));
192         printk("TSC2101_AUDIO_CTRL_7 = 0x%04x\n",       tsc2101_audio_read(TSC2101_AUDIO_CTRL_7));
193         printk("TSC2101_GPIO_CTRL = 0x%04x\n",  tsc2101_audio_read(TSC2101_GPIO_CTRL));
194         printk("TSC2101_AGC_CTRL = 0x%04x\n",   tsc2101_audio_read(TSC2101_AGC_CTRL));
195         printk("TSC2101_POWERDOWN_STS = 0x%04x\n",      tsc2101_audio_read(TSC2101_POWERDOWN_STS));
196         printk("TSC2101_MIC_AGC_CONTROL = 0x%04x\n",    tsc2101_audio_read(TSC2101_MIC_AGC_CONTROL));
197         printk("TSC2101_CELL_AGC_CONTROL = 0x%04x\n",   tsc2101_audio_read(TSC2101_CELL_AGC_CONTROL));
198 }
199 #endif
200
201 /*
202  * ALSA operations according to board file
203  */
204
205 /*
206  * Sample rate changing
207  */
208 void tsc2101_set_samplerate(long sample_rate)
209 {
210         u8 count = 0;
211         u16 data = 0;
212         int clkgdv = 0;
213
214         u16 srgr1, srgr2;
215         /* wait for any frame to complete */
216         udelay(125);
217         ADEBUG();
218
219         sample_rate     = sample_rate;
220         /* Search for the right sample rate */
221         while ((rate_reg_info[count].sample_rate != sample_rate) &&
222                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
223                 count++;
224         }
225         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
226                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
227                        (int) sample_rate);
228                 return;         // -EPERM;
229         }
230
231         /* Set AC1 */
232         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1);
233         /* Clear prev settings */
234         data    &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
235         data    |= AC1_DACFS(rate_reg_info[count].divisor) | 
236                         AC1_ADCFS(rate_reg_info[count].divisor);
237         tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data);
238
239         /* Set the AC3 */
240         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3);
241         /*Clear prev settings */
242         data    &= ~(AC3_REFFS | AC3_SLVMS);
243         data    |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
244 #ifdef TSC_MASTER
245         data    |= AC3_SLVMS;
246 #endif                          /* #ifdef TSC_MASTER */
247         tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
248
249         /* program the PLLs */
250         if (rate_reg_info[count].fs_44kHz) {
251                 /* 44.1 khz - 12 MHz Mclk */
252                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
253                                 PLL1_PVAL(1) | PLL1_I_VAL(7));  /* PVAL 1; I_VAL 7 */
254                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
255         } else {
256                 /* 48 khz - 12 Mhz Mclk */
257                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
258                                PLL1_PVAL(1) | PLL1_I_VAL(8));   /* PVAL 1; I_VAL 8 */
259                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
260         }
261
262         /* Set the sample rate */
263 #ifndef TSC_MASTER
264         clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
265         if (clkgdv)
266                 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
267         else
268                 return (1);
269
270         /* Stereo Mode */
271         srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
272 #else
273         srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
274         srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
275
276 #endif                          /* end of #ifdef TSC_MASTER */
277         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2);
278         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1);
279 }
280
281 void tsc2101_configure(void)
282 {
283 }
284
285 /*
286  *  Omap MCBSP clock and Power Management configuration
287  *  
288  *  Here we have some functions that allows clock to be enabled and
289  *   disabled only when needed. Besides doing clock configuration 
290  *   it allows turn on/turn off audio when necessary. 
291  */
292  
293 /*
294  * Do clock framework mclk search
295  */
296 void tsc2101_clock_setup(void)
297 {
298         tsc2101_mclk = clk_get(0, "mclk");
299 }
300
301 /*
302  * Do some sanity check, set clock rate, starts it and turn codec audio on
303  */
304 int tsc2101_clock_on(void) 
305 {
306         int     curUseCount;
307         uint    curRate;
308         int     err;
309
310         curUseCount     = clk_get_usecount(tsc2101_mclk);
311         DPRINTK("clock use count = %d\n", curUseCount);
312         if (curUseCount > 0) {
313                 // MCLK is already in use
314                 printk(KERN_WARNING
315                        "MCLK already in use at %d Hz. We change it to %d Hz\n",
316                        (uint) clk_get_rate(tsc2101_mclk),
317                        CODEC_CLOCK);
318         }
319         curRate = (uint)clk_get_rate(tsc2101_mclk);
320         DPRINTK("old clock rate = %d\n", curRate);
321         if (curRate != CODEC_CLOCK) {
322                 err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
323                 if (err) {
324                         printk(KERN_WARNING
325                                "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
326                         //return -ECANCELED;
327                 }
328         }
329         else
330         {
331                 printk(KERN_INFO
332                        "omap_alsa_tsc2101_clock_on(), no need to change rate, no need to change clock rate, rate already %d Hz.\n",
333                        CODEC_CLOCK);
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
353  *  codec audio off
354  */
355 int tsc2101_clock_off(void) 
356 {
357         int curUseCount;
358         int curRate;
359
360         curUseCount     = clk_get_usecount(tsc2101_mclk);
361         DPRINTK("clock use count = %d\n", curUseCount);
362         if  (curUseCount > 0) {
363                 curRate = clk_get_rate(tsc2101_mclk);
364                 DPRINTK("clock rate = %d\n", curRate);
365                 if (curRate != CODEC_CLOCK) {
366                         printk(KERN_WARNING
367                                "MCLK for audio should be %d Hz. But is %d Hz\n",
368                                (uint) clk_get_rate(tsc2101_mclk),
369                                CODEC_CLOCK);
370                 }
371                 clk_disable(tsc2101_mclk);
372                 DPRINTK("clock disabled\n");
373         }
374         tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
375                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
376         DPRINTK("audio codec off\n");
377 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
378         printk("tsc2101_clock_off()\n");
379         dump_tsc2101_audio_reg();
380 #endif  
381         return 0;       
382 }
383
384 int tsc2101_get_default_samplerate(void)
385 {
386         return DEFAULT_SAMPLE_RATE;
387 }
388
389 static int __init snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
390 {
391         int     ret;
392         struct  omap_alsa_codec_config *codec_cfg;
393         
394         codec_cfg = pdev->dev.platform_data;
395         if (codec_cfg != NULL) {
396                 codec_cfg->hw_constraints_rates = &tsc2101_hw_constraints_rates;
397                 codec_cfg->snd_omap_alsa_playback  = &tsc2101_snd_omap_alsa_playback;
398                 codec_cfg->snd_omap_alsa_capture  = &tsc2101_snd_omap_alsa_capture;
399                 codec_cfg->codec_configure_dev  = tsc2101_configure;
400                 codec_cfg->codec_set_samplerate = tsc2101_set_samplerate;
401                 codec_cfg->codec_clock_setup    = tsc2101_clock_setup;
402                 codec_cfg->codec_clock_on       = tsc2101_clock_on;
403                 codec_cfg->codec_clock_off      = tsc2101_clock_off;
404                 codec_cfg->get_default_samplerate = tsc2101_get_default_samplerate;
405                 ret     = snd_omap_alsa_post_probe(pdev, codec_cfg);
406         }
407         else
408                 ret = -ENODEV;
409         return ret;
410 }
411
412 static struct platform_driver omap_alsa_driver = {
413         .probe          = snd_omap_alsa_tsc2101_probe,
414         .remove         = snd_omap_alsa_remove,
415         .suspend        = snd_omap_alsa_suspend,
416         .resume         = snd_omap_alsa_resume,
417         .driver = {
418                 .name = "omap_alsa_mcbsp",
419         },
420 };
421
422 static int __init omap_alsa_tsc2101_init(void)
423 {
424         int err;
425         
426         ADEBUG();
427         err = platform_driver_register(&omap_alsa_driver);
428
429         return err;
430 }
431
432 static void __exit omap_alsa_tsc2101_exit(void)
433 {
434         ADEBUG();
435         platform_driver_unregister(&omap_alsa_driver);
436 }
437
438 module_init(omap_alsa_tsc2101_init);
439 module_exit(omap_alsa_tsc2101_exit);