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