]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-aic23.c
[PATCH] ARM: OMAP: Alsa modularisations and support for tsc2101 2/3 (round 2)
[linux-2.6-omap-h63xx.git] / sound / arm / omap / omap-alsa-aic23.c
1 /*
2  * arch/arm/mach-omap1/omap-alsa-aic23.c
3  * 
4  * Alsa codec Driver for AIC23 chip on OSK5912 platform board
5  *
6  * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
7  * Written by Daniel Petrini, David Cohen, Anderson Briglia
8  *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
9  *
10  * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
11  * 
12  * Based in former alsa driver for osk and oss driver
13  *
14  * This program is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by the
16  * Free Software Foundation; either version 2 of the License, or (at your
17  * option) any later version.
18  */
19
20 #include <sound/driver.h>
21 #include <sound/core.h>
22 #include <sound/pcm.h>
23 #include <sound/initval.h>
24 #include <sound/control.h>
25 #include <linux/clk.h>
26 #include <asm/arch/clock.h>
27 #include <asm/arch/aic23.h>
28
29 #include <asm/arch/omap-alsa.h>
30 #include "omap-alsa-aic23.h"
31
32 static struct clk *aic23_mclk = 0;
33
34 /* aic23 related */
35 static const struct aic23_samplerate_reg_info
36  rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
37         {4000, 0x06, 1},                /*  4000 */
38         {8000, 0x06, 0},                /*  8000 */
39         {16000, 0x0C, 1},               /* 16000 */
40         {22050, 0x11, 1},               /* 22050 */
41         {24000, 0x00, 1},               /* 24000 */
42         {32000, 0x0C, 0},               /* 32000 */
43         {44100, 0x11, 0},               /* 44100 */
44         {48000, 0x00, 0},               /* 48000 */
45         {88200, 0x1F, 0},               /* 88200 */
46         {96000, 0x0E, 0},               /* 96000 */
47 };
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         4000, 8000, 16000, 22050,
59         24000, 32000, 44100,
60         48000, 88200, 96000,
61 };
62
63 static snd_pcm_hw_constraint_list_t aic23_hw_constraints_rates = {
64         .count = ARRAY_SIZE(rates),
65         .list = rates,
66         .mask = 0,
67 };
68
69 static snd_pcm_hardware_t aic23_snd_omap_alsa_playback = {
70         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
71                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
72         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
73         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
74                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
75                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
76                   SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
77                   SNDRV_PCM_RATE_KNOT),
78         .rate_min = 8000,
79         .rate_max = 96000,
80         .channels_min = 2,
81         .channels_max = 2,
82         .buffer_bytes_max = 128 * 1024,
83         .period_bytes_min = 32,
84         .period_bytes_max = 8 * 1024,
85         .periods_min = 16,
86         .periods_max = 255,
87         .fifo_size = 0,
88 };
89
90 static snd_pcm_hardware_t aic23_snd_omap_alsa_capture = {
91         .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
92                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
93         .formats = (SNDRV_PCM_FMTBIT_S16_LE),
94         .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
95                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
96                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
97                   SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
98                   SNDRV_PCM_RATE_KNOT),
99         .rate_min = 8000,
100         .rate_max = 96000,
101         .channels_min = 2,
102         .channels_max = 2,
103         .buffer_bytes_max = 128 * 1024,
104         .period_bytes_min = 32,
105         .period_bytes_max = 8 * 1024,
106         .periods_min = 16,
107         .periods_max = 255,
108         .fifo_size = 0,
109 };
110
111 /*
112  * Codec/mcbsp init and configuration section
113  * codec dependent code.
114  */
115
116 extern int tlv320aic23_write_value(u8 reg, u16 value);
117
118 /* TLV320AIC23 is a write only device */
119 void audio_aic23_write(u8 address, u16 data)
120 {
121         tlv320aic23_write_value(address, data);
122 }
123 EXPORT_SYMBOL_GPL(audio_aic23_write);
124
125 /*
126  * Sample rate changing
127  */
128 void aic23_set_samplerate(long rate)
129 {
130         u8 count = 0;
131         u16 data = 0;
132
133         /* Fix the rate if it has a wrong value */
134         if (rate >= 96000)
135                 rate = 96000;
136         else if (rate >= 88200)
137                 rate = 88200;
138         else if (rate >= 48000)
139                 rate = 48000;
140         else if (rate >= 44100)
141                 rate = 44100;
142         else if (rate >= 32000)
143                 rate = 32000;
144         else if (rate >= 24000)
145                 rate = 24000;
146         else if (rate >= 22050)
147                 rate = 22050;
148         else if (rate >= 16000)
149                 rate = 16000;
150         else if (rate >= 8000)
151                 rate = 8000;
152         else
153                 rate = 4000;
154
155         /* Search for the right sample rate */
156         /* Verify what happens if the rate is not supported
157          * now it goes to 96Khz */
158         while ((rate_reg_info[count].sample_rate != rate) &&
159                (count < (NUMBER_SAMPLE_RATES_SUPPORTED - 1))) {
160                 count++;
161         }
162
163         data = (rate_reg_info[count].divider << CLKIN_SHIFT) |
164             (rate_reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
165
166         audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
167 }
168
169 inline void aic23_configure(void)
170 {
171         /* Reset codec */
172         audio_aic23_write(RESET_CONTROL_ADDR, 0);
173
174         /* Initialize the AIC23 internal state */
175
176         /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
177         audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DEFAULT_ANALOG_AUDIO_CONTROL);
178
179         /* Digital audio path control, de-emphasis control 44.1kHz */
180         audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
181
182         /* Digital audio interface, master/slave mode, I2S, 16 bit */
183 #ifdef AIC23_MASTER
184         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR,
185                           MS_MASTER | IWL_16 | FOR_DSP);
186 #else
187         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
188 #endif
189
190         /* Enable digital interface */
191         audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
192 }
193
194 /*
195  *  Omap MCBSP clock configuration and Power Management
196  *  
197  *  Here we have some functions that allows clock to be enabled and
198  *   disabled only when needed. Besides doing clock configuration 
199  *   it allows turn on/turn off audio when necessary. 
200  */
201 /*
202  * Do clock framework mclk search
203  */
204 void aic23_clock_setup(void)
205 {
206         aic23_mclk = clk_get(0, "mclk");
207 }
208
209 /*
210  * Do some sanity check, set clock rate, starts it and
211  *  turn codec audio on 
212  */
213 int aic23_clock_on(void)
214 {
215         if (clk_get_usecount(aic23_mclk) > 0) {
216                 /* MCLK is already in use */
217                 printk(KERN_WARNING
218                        "MCLK in use at %d Hz. We change it to %d Hz\n",
219                        (uint) clk_get_rate(aic23_mclk),
220                        CODEC_CLOCK);
221         }
222         
223         if (clk_set_rate(aic23_mclk, CODEC_CLOCK)) {
224                 printk(KERN_ERR
225                        "Cannot set MCLK for AIC23 CODEC\n");
226                 return -ECANCELED;
227         }
228
229         clk_enable(aic23_mclk);
230
231         printk(KERN_DEBUG
232                 "MCLK = %d [%d], usecount = %d\n",
233                (uint) clk_get_rate(aic23_mclk), CODEC_CLOCK,
234                clk_get_usecount(aic23_mclk));
235
236         /* Now turn the audio on */
237         audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 
238                           ~DEVICE_POWER_OFF & ~OUT_OFF & ~DAC_OFF &
239                           ~ADC_OFF & ~MIC_OFF & ~LINE_OFF);     
240         return 0;
241 }
242 /*
243  * Do some sanity check, turn clock off and then turn
244  *  codec audio off
245  */
246 int aic23_clock_off(void)
247 {
248         if  (clk_get_usecount(aic23_mclk) > 0) { 
249                 if (clk_get_rate(aic23_mclk) != CODEC_CLOCK) {
250                         printk(KERN_WARNING
251                                "MCLK for audio should be %d Hz. But is %d Hz\n",
252                                (uint) clk_get_rate(aic23_mclk),
253                                CODEC_CLOCK);
254                 }
255
256                 clk_disable(aic23_mclk);
257         }
258         
259         audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
260                           DEVICE_POWER_OFF | OUT_OFF | DAC_OFF |
261                           ADC_OFF | MIC_OFF | LINE_OFF);        
262         return 0;
263 }
264
265 int aic23_get_default_samplerate(void)
266 {
267         return DEFAULT_SAMPLE_RATE;
268 }
269
270 static int __init snd_omap_alsa_aic23_probe(struct platform_device *pdev)
271 {
272         int     ret;
273         struct  omap_alsa_codec_config *codec_cfg;
274         
275         codec_cfg = pdev->dev.platform_data;
276         if (codec_cfg != NULL) {
277                 codec_cfg->hw_constraints_rates = &aic23_hw_constraints_rates;
278                 codec_cfg->snd_omap_alsa_playback  = &aic23_snd_omap_alsa_playback;
279                 codec_cfg->snd_omap_alsa_capture  = &aic23_snd_omap_alsa_capture;               
280                 codec_cfg->codec_configure_dev  = aic23_configure;
281                 codec_cfg->codec_set_samplerate = aic23_set_samplerate;
282                 codec_cfg->codec_clock_setup    = aic23_clock_setup;
283                 codec_cfg->codec_clock_on       = aic23_clock_on;
284                 codec_cfg->codec_clock_off      = aic23_clock_off;
285                 codec_cfg->get_default_samplerate = aic23_get_default_samplerate;
286                 ret     = snd_omap_alsa_post_probe(pdev, codec_cfg);
287         }
288         else
289                 ret = -ENODEV;
290         return ret;
291 }
292
293 static struct platform_driver omap_alsa_driver = {
294         .probe          = snd_omap_alsa_aic23_probe,
295         .remove         = snd_omap_alsa_remove,
296         .suspend        = snd_omap_alsa_suspend,
297         .resume         = snd_omap_alsa_resume,
298         .driver = {
299                 .name = "omap_alsa_mcbsp",
300         },
301 };
302
303 static int __init omap_alsa_aic23_init(void)
304 {
305         int err;
306         
307         ADEBUG();
308         err = platform_driver_register(&omap_alsa_driver);
309
310         return err;
311 }
312
313 static void __exit omap_alsa_aic23_exit(void)
314 {
315         ADEBUG();
316         
317         platform_driver_unregister(&omap_alsa_driver);
318 }
319
320 module_init(omap_alsa_aic23_init);
321 module_exit(omap_alsa_aic23_exit);