2 * arch/arm/mach-omap1/omap-alsa-aic23.c
4 * Alsa codec Driver for AIC23 chip on OSK5912 platform board
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
10 * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
12 * Based in former alsa driver for osk and oss driver
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.
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 <asm/arch/clock.h>
26 #include <asm/arch/aic23.h>
28 #include <asm/arch/omap-alsa.h>
29 #include "omap-alsa-aic23.h"
31 static struct clk *aic23_mclk;
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 */
49 * Hardware capabilities
53 * DAC USB-mode sampling rates (MCLK = 12 MHz)
54 * The rates and rate_reg_into MUST be in the same order
56 static unsigned int rates[] = {
57 4000, 8000, 16000, 22050,
62 static struct snd_pcm_hw_constraint_list aic23_hw_constraints_rates = {
63 .count = ARRAY_SIZE(rates),
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 |
81 .buffer_bytes_max = 128 * 1024,
82 .period_bytes_min = 32,
83 .period_bytes_max = 8 * 1024,
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 |
102 .buffer_bytes_max = 128 * 1024,
103 .period_bytes_min = 32,
104 .period_bytes_max = 8 * 1024,
111 * Codec/mcbsp init and configuration section
112 * codec dependent code.
115 /* TLV320AIC23 is a write only device */
116 void audio_aic23_write(u8 address, u16 data)
118 aic23_write_value(address, data);
120 EXPORT_SYMBOL_GPL(audio_aic23_write);
123 * Sample rate changing
125 void aic23_set_samplerate(long rate)
130 /* Fix the rate if it has a wrong value */
133 else if (rate >= 88200)
135 else if (rate >= 48000)
137 else if (rate >= 44100)
139 else if (rate >= 32000)
141 else if (rate >= 24000)
143 else if (rate >= 22050)
145 else if (rate >= 16000)
147 else if (rate >= 8000)
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))) {
160 data = (rate_reg_info[count].divider << CLKIN_SHIFT) |
161 (rate_reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
163 audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
166 inline void aic23_configure(void)
169 audio_aic23_write(RESET_CONTROL_ADDR, 0);
171 /* Initialize the AIC23 internal state */
174 * Analog audio path control, DAC selected,
175 * delete INSEL_MIC for line-in
177 audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR,
178 DEFAULT_ANALOG_AUDIO_CONTROL);
180 /* Digital audio path control, de-emphasis control 44.1kHz */
181 audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
183 /* Digital audio interface, master/slave mode, I2S, 16 bit */
185 audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR,
186 MS_MASTER | IWL_16 | FOR_DSP);
188 audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
191 /* Enable digital interface */
192 audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
196 * OMAP MCBSP clock configuration and Power Management
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.
203 * Do clock framework mclk search
205 void aic23_clock_setup(void)
207 aic23_mclk = clk_get(0, "mclk");
211 * Do some sanity check, set clock rate, starts it and
212 * turn codec audio on
214 int aic23_clock_on(void)
218 if (clk_get_usecount(aic23_mclk) > 0) {
219 /* MCLK is already in use */
221 "MCLK in use at %d Hz. We change it to %d Hz\n",
222 (uint) clk_get_rate(aic23_mclk),
225 curRate = (uint)clk_get_rate(aic23_mclk);
226 if (curRate != CODEC_CLOCK) {
227 if (clk_set_rate(aic23_mclk, CODEC_CLOCK)) {
229 "Cannot set MCLK for AIC23 CODEC\n");
233 clk_enable(aic23_mclk);
236 "MCLK = %d [%d], usecount = %d\n",
237 (uint) clk_get_rate(aic23_mclk), CODEC_CLOCK,
238 clk_get_usecount(aic23_mclk));
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);
248 * Do some sanity check, turn clock off and then turn
251 int aic23_clock_off(void)
253 if (clk_get_usecount(aic23_mclk) > 0) {
254 if (clk_get_rate(aic23_mclk) != CODEC_CLOCK) {
256 "MCLK for audio should be %d Hz. But is %d Hz\n",
257 (uint) clk_get_rate(aic23_mclk),
261 clk_disable(aic23_mclk);
264 audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
265 DEVICE_POWER_OFF | OUT_OFF | DAC_OFF |
266 ADC_OFF | MIC_OFF | LINE_OFF);
270 int aic23_get_default_samplerate(void)
272 return DEFAULT_SAMPLE_RATE;
275 static int __devinit snd_omap_alsa_aic23_probe(struct platform_device *pdev)
278 struct omap_alsa_codec_config *codec_cfg;
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);
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,
305 .name = "omap_alsa_mcbsp",
309 static int __init omap_alsa_aic23_init(void)
314 err = platform_driver_register(&omap_alsa_driver);
319 static void __exit omap_alsa_aic23_exit(void)
323 platform_driver_unregister(&omap_alsa_driver);
326 module_init(omap_alsa_aic23_init);
327 module_exit(omap_alsa_aic23_exit);