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