]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/omap-audio-aic23.c
Merge with /home/tmlind/src/kernel/linux-2.6
[linux-2.6-omap-h63xx.git] / sound / oss / omap-audio-aic23.c
1 /*
2  * linux/sound/oss/omap-audio-aic23.c
3  *
4  * Glue audio driver for TI TLV320AIC23 codec
5  *
6  * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
7  * Copyright (C) 2001, Steve Johnson <stevej@ridgerun.com>
8  * Copyright (C) 2004 Texas Instruments, Inc.
9  * Copyright (C) 2005 Dirk Behme <dirk.behme@de.bosch.com>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation; either version 2 of the License, or (at your
14  * option) any later version.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * You should have received a copy of the  GNU General Public License along
28  * with this program; if not, write  to the Free Software Foundation, Inc.,
29  * 675 Mass Ave, Cambridge, MA 02139, USA.
30  */
31
32 #include <linux/module.h>
33 #include <linux/init.h>
34 #include <linux/types.h>
35 #include <linux/delay.h>
36 #include <linux/pm.h>
37 #include <linux/errno.h>
38 #include <linux/sound.h>
39 #include <linux/soundcard.h>
40 #include <linux/clk.h>
41
42 #include <asm/uaccess.h>
43 #include <asm/hardware.h>
44 #include <asm/io.h>
45 #include <asm/mach-types.h>
46
47 #include <asm/arch/mcbsp.h>
48 #include <asm/arch/fpga.h>
49 #include <asm/arch/aic23.h>
50 #include <asm/arch/clock.h>
51
52 #include "omap-audio.h"
53 #include "omap-audio-dma-intfc.h"
54
55 #ifdef CONFIG_PROC_FS
56 #include <linux/proc_fs.h>
57 #define PROC_START_FILE "driver/aic23-audio-start"
58 #define PROC_STOP_FILE  "driver/aic23-audio-stop"
59 #endif
60
61 //#define DEBUG
62
63 #ifdef DEBUG
64 #define DPRINTK(ARGS...)  printk("<%s>: ",__FUNCTION__);printk(ARGS)
65 #else
66 #define DPRINTK( x... )
67 #endif
68
69 #define CODEC_NAME               "AIC23"
70
71 #if CONFIG_MACH_OMAP_OSK
72 #define PLATFORM_NAME            "OMAP OSK"
73 #elif CONFIG_MACH_OMAP_INNOVATOR
74 #define PLATFORM_NAME            "OMAP INNOVATOR"
75 #else
76 #error "Unsupported plattform"
77 #endif
78
79 /* Define to set the AIC23 as the master w.r.t McBSP */
80 #define AIC23_MASTER
81
82 #define CODEC_CLOCK                   12000000
83
84 /*
85  * AUDIO related MACROS
86  */
87 #define DEFAULT_BITPERSAMPLE          16
88 #define AUDIO_RATE_DEFAULT            44100
89
90 /* Select the McBSP For Audio */
91 #define AUDIO_MCBSP                   OMAP_MCBSP1
92
93 #define REC_MASK                      (SOUND_MASK_LINE | SOUND_MASK_MIC)
94 #define DEV_MASK                      (REC_MASK | SOUND_MASK_VOLUME)
95
96 #define SET_VOLUME                    1
97 #define SET_LINE                      2
98
99 #define DEFAULT_OUTPUT_VOLUME         93
100 #define DEFAULT_INPUT_VOLUME          0 /* 0 ==> mute line in */
101
102 #define OUTPUT_VOLUME_MIN             LHV_MIN
103 #define OUTPUT_VOLUME_MAX             LHV_MAX
104 #define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
105 #define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
106
107 #define INPUT_VOLUME_MIN              LIV_MIN
108 #define INPUT_VOLUME_MAX              LIV_MAX
109 #define INPUT_VOLUME_RANGE            (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
110 #define INPUT_VOLUME_MASK             INPUT_VOLUME_MAX
111
112 #define NUMBER_SAMPLE_RATES_SUPPORTED 9
113
114 /*
115  * HW interface start and stop helper functions
116  */
117 static int audio_ifc_start(void)
118 {
119         omap_mcbsp_start(AUDIO_MCBSP);
120         return 0;
121 }
122
123 static int audio_ifc_stop(void)
124 {
125         omap_mcbsp_stop(AUDIO_MCBSP);
126         return 0;
127 }
128
129 static audio_stream_t output_stream = {
130         .id              = "AIC23 out",
131         .dma_dev         = OMAP_DMA_MCBSP1_TX,
132         .input_or_output = FMODE_WRITE,
133         .hw_start       = audio_ifc_start,
134         .hw_stop         = audio_ifc_stop
135 };
136
137 static audio_stream_t input_stream = {
138         .id              = "AIC23 in",
139         .dma_dev         = OMAP_DMA_MCBSP1_RX,
140         .input_or_output = FMODE_READ,
141         .hw_start       = audio_ifc_start,
142         .hw_stop         = audio_ifc_stop
143 };
144
145 static struct clk *aic23_mclk = 0;
146
147 static int audio_dev_id, mixer_dev_id;
148
149 static struct aic23_local_info {
150         u8  volume;
151         u16 volume_reg;
152         u8  line;
153         u8  mic;
154         u16 input_volume_reg;
155         int mod_cnt;
156 } aic23_local;
157
158 struct sample_rate_reg_info {
159         u32 sample_rate;
160         u8  control;            /* SR3, SR2, SR1, SR0 and BOSR */
161         u8  divider;            /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
162 };
163
164 /* To Store the default sample rate */
165 static long audio_samplerate = AUDIO_RATE_DEFAULT;
166
167 /* DAC USB-mode sampling rates (MCLK = 12 MHz) */
168 static const struct sample_rate_reg_info
169 reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
170         {96000, 0x0E, 0},
171         {88200, 0x1F, 0},
172         {48000, 0x00, 0},
173         {44100, 0x11, 0},
174         {32000, 0x0C, 0},
175         {24000, 0x00, 1},
176         {16000, 0x0C, 1},
177         { 8000, 0x06, 0},
178         { 4000, 0x06, 1},
179 };
180
181 static struct omap_mcbsp_reg_cfg initial_config = {
182         .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
183         .spcr1 = RINTM(3) | RRST,
184         .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
185         RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
186         .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
187         .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
188         XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
189         .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
190         .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
191         .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
192 #ifndef AIC23_MASTER
193         /* configure McBSP to be the I2S master */
194         .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
195 #else
196         /* configure McBSP to be the I2S slave */
197         .pcr0  = CLKXP | CLKRP,
198 #endif /* AIC23_MASTER */
199 };
200
201 static void omap_aic23_initialize(void *dummy);
202 static void omap_aic23_shutdown(void *dummy);
203 static int  omap_aic23_ioctl(struct inode *inode, struct file *file,
204                              uint cmd, ulong arg);
205 static int  omap_aic23_probe(void);
206 #ifdef MODULE
207 static void omap_aic23_remove(void);
208 #endif
209 static int  omap_aic23_suspend(void);
210 static int  omap_aic23_resume(void);
211 static inline void aic23_configure(void);
212 static int  mixer_open(struct inode *inode, struct file *file);
213 static int  mixer_release(struct inode *inode, struct file *file);
214 static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
215                         ulong arg);
216
217 #ifdef CONFIG_PROC_FS
218 static int codec_start(char *buf, char **start, off_t offset, int count,
219                        int *eof, void *data);
220 static int codec_stop(char *buf, char **start, off_t offset, int count,
221                       int *eof, void *data);
222 #endif
223
224
225 /* File Op structure for mixer */
226 static struct file_operations omap_mixer_fops = {
227         .open           = mixer_open,
228         .release        = mixer_release,
229         .ioctl          = mixer_ioctl,
230         .owner          = THIS_MODULE
231 };
232
233 /* To store characteristic info regarding the codec for the audio driver */
234 static audio_state_t aic23_state = {
235         .output_stream  = &output_stream,
236         .input_stream   = &input_stream,
237 /*      .need_tx_for_rx = 1, //Once the Full Duplex works  */
238         .need_tx_for_rx = 0,
239         .hw_init        = omap_aic23_initialize,
240         .hw_shutdown    = omap_aic23_shutdown,
241         .client_ioctl   = omap_aic23_ioctl,
242         .hw_probe       = omap_aic23_probe,
243         .hw_remove      =  __exit_p(omap_aic23_remove),
244         .hw_suspend     = omap_aic23_suspend,
245         .hw_resume      = omap_aic23_resume,
246         .sem        = __SEMAPHORE_INIT(aic23_state.sem, 1),
247 };
248
249 /* This will be defined in the audio.h */
250 static struct file_operations *omap_audio_fops;
251
252 extern int tlv320aic23_write_value(u8 reg, u16 value);
253
254 /* TLV320AIC23 is a write only device */
255 static __inline__ void audio_aic23_write(u8 address, u16 data)
256 {
257         tlv320aic23_write_value(address, data);
258 }
259
260 static int aic23_update(int flag, int val)
261 {
262         u16 volume;
263
264         /* Ignore separate left/right channel for now,
265            even the codec does support it. */
266         val &= 0xff;
267
268         if (val < 0 || val > 100) {
269                 printk(KERN_ERR "Trying a bad volume value(%d)!\n",val);
270                 return -EPERM;
271         }
272
273         switch (flag) {
274         case SET_VOLUME:
275                 // Convert 0 -> 100 volume to 0x00 (LHV_MIN) -> 0x7f (LHV_MAX) 
276                 // volume range
277                 volume = ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
278                 
279                 // R/LHV[6:0] 1111111 (+6dB) to 0000000 (-73dB) in 1db steps,
280                 // default 1111001 (0dB)
281                 aic23_local.volume_reg &= ~OUTPUT_VOLUME_MASK;
282                 aic23_local.volume_reg |= volume;
283                 audio_aic23_write(LEFT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
284                 audio_aic23_write(RIGHT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
285                 break;
286
287         case SET_LINE:
288                 // Convert 0 -> 100 volume to 0x0 (LIV_MIN) -> 0x1f (LIV_MAX) 
289                 // volume range
290                 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
291
292                 // R/LIV[4:0] 11111 (+12dB) to 00000 (-34.5dB) in 1.5dB steps,
293                 // default 10111 (0dB)
294                 aic23_local.input_volume_reg &= ~INPUT_VOLUME_MASK;
295                 aic23_local.input_volume_reg |= volume;
296                 audio_aic23_write(LEFT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
297                 audio_aic23_write(RIGHT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
298                 break;
299         }
300         return 0;
301 }
302
303 static int mixer_open(struct inode *inode, struct file *file)
304 {
305         /* Any mixer specific initialization */
306
307         return 0;
308 }
309
310 static int mixer_release(struct inode *inode, struct file *file)
311 {
312         /* Any mixer specific Un-initialization */
313
314         return 0;
315 }
316
317 static int
318 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
319 {
320         int val;
321         int ret = 0;
322         int nr = _IOC_NR(cmd);
323
324         /*
325          * We only accept mixer (type 'M') ioctls.
326          */
327         if (_IOC_TYPE(cmd) != 'M')
328                 return -EINVAL;
329
330         DPRINTK(" 0x%08x\n", cmd);
331
332         if (cmd == SOUND_MIXER_INFO) {
333                 struct mixer_info mi;
334
335                 strncpy(mi.id, "AIC23", sizeof(mi.id));
336                 strncpy(mi.name, "TI AIC23", sizeof(mi.name));
337                 mi.modify_counter = aic23_local.mod_cnt;
338                 return copy_to_user((void *)arg, &mi, sizeof(mi));
339         }
340
341         if (_IOC_DIR(cmd) & _IOC_WRITE) {
342                 ret = get_user(val, (int *)arg);
343                 if (ret)
344                         goto out;
345
346         
347                 switch (nr) {
348                 case SOUND_MIXER_VOLUME:
349                         aic23_local.volume = val;
350                         aic23_local.mod_cnt++;
351                         ret = aic23_update(SET_VOLUME, val);
352                         break;
353
354                 case SOUND_MIXER_LINE:
355                         aic23_local.line = val;
356                         aic23_local.mod_cnt++;
357                         ret = aic23_update(SET_LINE, val);
358                         break;
359
360                 case SOUND_MIXER_MIC:
361                         aic23_local.mic = val;
362                         aic23_local.mod_cnt++;
363                         ret = aic23_update(SET_LINE, val);
364                         break;
365
366                 case SOUND_MIXER_RECSRC:
367                         break;
368
369                 default:
370                         ret = -EINVAL;
371                 }
372         }
373
374         if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
375                 ret = 0;
376
377                 switch (nr) {
378                 case SOUND_MIXER_VOLUME:
379                         val = aic23_local.volume;
380                         break;
381                 case SOUND_MIXER_LINE:
382                         val = aic23_local.line;
383                         break;
384                 case SOUND_MIXER_MIC:
385                         val = aic23_local.mic;
386                         break;
387                 case SOUND_MIXER_RECSRC:
388                         val = REC_MASK;
389                         break;
390                 case SOUND_MIXER_RECMASK:
391                         val = REC_MASK;
392                         break;
393                 case SOUND_MIXER_DEVMASK:
394                         val = DEV_MASK;
395                         break;
396                 case SOUND_MIXER_CAPS:
397                         val = 0;
398                         break;
399                 case SOUND_MIXER_STEREODEVS:
400                         val = 0;
401                         break;
402                 default:
403                         val = 0;
404                         ret = -EINVAL;
405                         break;
406                 }
407
408                 if (ret == 0)
409                         ret = put_user(val, (int *)arg);
410         }
411 out:
412         return ret;
413
414 }
415
416 int omap_set_samplerate(long sample_rate)
417 {
418         u8 count = 0;
419         u16 data = 0;
420         /* wait for any frame to complete */
421         udelay(125);
422
423         /* Search for the right sample rate */
424         while ((reg_info[count].sample_rate != sample_rate) &&
425                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
426                 count++;
427         }
428         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
429                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
430                        (int)sample_rate);
431                 return -EPERM;
432         }
433
434         if (machine_is_omap_innovator()) {
435                 /* set the CODEC clock input source to 12.000MHz */
436                 fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~0x01, 
437                            OMAP1510_FPGA_POWER);
438         }
439
440         data = (reg_info[count].divider << CLKIN_SHIFT) | 
441                 (reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
442
443         audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
444
445         audio_samplerate = sample_rate;
446
447 #ifndef AIC23_MASTER
448         {
449                 int clkgdv = 0;
450                 /* 
451                    Set Sample Rate at McBSP
452
453                    Formula : 
454                    Codec System Clock = CODEC_CLOCK, or half if clock_divider = 1;
455                    clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1);
456
457                    FWID = BitsPerSample - 1;
458                    FPER = (BitsPerSample * 2) - 1;
459                 */  
460                 if (reg_info[count].divider)
461                         clkgdv = CODEC_CLOCK / 2;
462                 else 
463                         clkgdv = CODEC_CLOCK;
464
465                 clkgdv = (clkgdv / (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1;
466
467                 initial_config.srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
468
469                 initial_config.srgr2 =
470                         (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
471
472                 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
473         }
474 #endif /* AIC23_MASTER */
475
476         return 0;
477 }
478
479 static void omap_aic23_initialize(void *dummy)
480 {
481         DPRINTK("entry\n");
482
483         /* initialize with default sample rate */
484         audio_samplerate = AUDIO_RATE_DEFAULT;
485
486         omap_mcbsp_request(AUDIO_MCBSP);
487
488         /* if configured, then stop mcbsp */
489         omap_mcbsp_stop(AUDIO_MCBSP);
490
491         omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
492         omap_mcbsp_start(AUDIO_MCBSP);
493         aic23_configure();
494
495         DPRINTK("exit\n");
496 }
497
498 static void omap_aic23_shutdown(void *dummy)
499 {
500         /*
501           Turn off codec after it is done.
502           Can't do it immediately, since it may still have
503           buffered data.
504
505           Wait 20ms (arbitrary value) and then turn it off.
506         */
507
508         set_current_state(TASK_INTERRUPTIBLE);
509         schedule_timeout(2);
510
511         omap_mcbsp_stop(AUDIO_MCBSP);
512         omap_mcbsp_free(AUDIO_MCBSP);
513
514         audio_aic23_write(RESET_CONTROL_ADDR, 0);
515         audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0xff);
516 }
517
518 static inline void aic23_configure()
519 {
520         /* Reset codec */
521         audio_aic23_write(RESET_CONTROL_ADDR, 0);
522
523         /* Initialize the AIC23 internal state */
524
525         /* Left/Right line input volume control */
526         aic23_local.line = DEFAULT_INPUT_VOLUME;
527         aic23_local.mic = DEFAULT_INPUT_VOLUME;
528         aic23_update(SET_LINE, DEFAULT_INPUT_VOLUME);
529
530         /* Left/Right headphone channel volume control */
531         /* Zero-cross detect on */
532         aic23_local.volume_reg = LZC_ON;
533         aic23_update(SET_VOLUME, aic23_local.volume);
534
535         /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
536         audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DAC_SELECTED | INSEL_MIC);
537
538         /* Digital audio path control, de-emphasis control 44.1kHz */
539         audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
540
541         /* Power control, everything is on */
542         audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0);
543
544         /* Digital audio interface, master/slave mode, I2S, 16 bit */
545 #ifdef AIC23_MASTER
546         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, MS_MASTER | IWL_16 | FOR_DSP);
547 #else
548         audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
549 #endif /* AIC23_MASTER */
550
551         /* Enable digital interface */
552         audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
553
554         /* clock configuration */
555         omap_set_samplerate(audio_samplerate);
556 }
557
558 static int
559 omap_aic23_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
560 {
561         long val;
562         int ret = 0;
563
564         DPRINTK(" 0x%08x\n", cmd);
565
566         /*
567          * These are platform dependent ioctls which are not handled by the
568          * generic omap-audio module.
569          */
570         switch (cmd) {
571         case SNDCTL_DSP_STEREO:
572                 ret = get_user(val, (int *)arg);
573                 if (ret)
574                         return ret;
575                 /* the AIC23 is stereo only */
576                 ret = (val == 0) ? -EINVAL : 1;
577                 return put_user(ret, (int *)arg);
578
579         case SNDCTL_DSP_CHANNELS:
580         case SOUND_PCM_READ_CHANNELS:
581                 /* the AIC23 is stereo only */
582                 return put_user(2, (long *)arg);
583
584         case SNDCTL_DSP_SPEED:
585                 ret = get_user(val, (long *)arg);
586                 if (ret)
587                         break;
588                 ret = omap_set_samplerate(val);
589                 if (ret)
590                         break;
591                 /* fall through */
592
593         case SOUND_PCM_READ_RATE:
594                 return put_user(audio_samplerate, (long *)arg);
595
596         case SOUND_PCM_READ_BITS:
597         case SNDCTL_DSP_SETFMT:
598         case SNDCTL_DSP_GETFMTS:
599                 /* we can do 16-bit only */
600                 return put_user(AFMT_S16_LE, (long *)arg);
601
602         default:
603                 /* Maybe this is meant for the mixer (As per OSS Docs) */
604                 return mixer_ioctl(inode, file, cmd, arg);
605         }
606
607         return ret;
608 }
609
610 static int omap_aic23_probe(void)
611 {
612         /* Get the fops from audio oss driver */
613         if (!(omap_audio_fops = audio_get_fops())) {
614                 printk(KERN_ERR "Unable to get the file operations for AIC23 OSS driver\n");
615                 audio_unregister_codec(&aic23_state);
616                 return -EPERM;
617         }
618
619         aic23_local.volume = DEFAULT_OUTPUT_VOLUME;
620
621         /* register devices */
622         audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
623         mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
624
625 #ifdef CONFIG_PROC_FS
626         create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
627                                NULL /* parent dir */ ,
628                                codec_start, NULL /* client data */ );
629
630         create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
631                                NULL /* parent dir */ ,
632                                codec_stop, NULL /* client data */ );
633 #endif
634
635         /* Announcement Time */
636         printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
637                " audio support initialized\n");
638         return 0;
639 }
640
641 #ifdef MODULE
642 static void __exit omap_aic23_remove(void)
643 {
644         /* Un-Register the codec with the audio driver */
645         unregister_sound_dsp(audio_dev_id);
646         unregister_sound_mixer(mixer_dev_id);
647
648 #ifdef CONFIG_PROC_FS
649         remove_proc_entry(PROC_START_FILE, NULL);
650         remove_proc_entry(PROC_STOP_FILE, NULL);
651 #endif
652 }
653 #endif /* MODULE */
654
655 static int omap_aic23_suspend(void)
656 {
657         /* Empty for the moment */
658         return 0;
659 }
660
661 static int omap_aic23_resume(void)
662 {
663         /* Empty for the moment */
664         return 0;
665 }
666
667 static int __init audio_aic23_init(void)
668 {
669
670         int err = 0;
671
672         if (machine_is_omap_h2() || machine_is_omap_h3())
673                 return -ENODEV;
674
675         if (machine_is_omap_osk()) {
676                 /* Set MCLK to be clock input for AIC23 */
677                 aic23_mclk = clk_get(0, "mclk");
678             
679                 if(clk_get_rate( aic23_mclk) != CODEC_CLOCK){
680                         /* MCLK ist not at CODEC_CLOCK */
681                         if( clk_get_usecount(aic23_mclk) > 0 ){
682                                 /* MCLK is already in use */
683                                 printk(KERN_WARNING "MCLK in use at %d Hz. We change it to %d Hz\n",
684                                        (uint)clk_get_rate( aic23_mclk), CODEC_CLOCK);
685                         }
686                         if( clk_set_rate( aic23_mclk, CODEC_CLOCK ) ){
687                                 printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
688                                 return -ECANCELED;
689                         }
690                 }
691
692                 clk_enable( aic23_mclk );
693
694                 DPRINTK("MCLK = %d [%d], usecount = %d\n",(uint)clk_get_rate( aic23_mclk ), 
695                         CODEC_CLOCK, clk_get_usecount( aic23_mclk));
696         }
697
698         if (machine_is_omap_innovator()) {
699                 u8 fpga;
700                 /*
701                   Turn on chip select for CODEC (shared with touchscreen).  
702                   Don't turn it back off, in case touch screen needs it.
703                 */                           
704                 fpga = fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
705                 fpga |= 0x4;
706                 fpga_write(fpga, OMAP1510_FPGA_TOUCHSCREEN);
707         }
708
709         /* register the codec with the audio driver */
710         if ((err = audio_register_codec(&aic23_state))) {
711                 printk(KERN_ERR
712                        "Failed to register AIC23 driver with Audio OSS Driver\n");
713         }
714
715         return err;
716 }
717
718 static void __exit audio_aic23_exit(void)
719 {
720         (void)audio_unregister_codec(&aic23_state);
721         return;
722 }
723
724 #ifdef CONFIG_PROC_FS
725 static int codec_start(char *buf, char **start, off_t offset, int count,
726                        int *eof, void *data)
727 {
728         void *foo = NULL;
729
730         omap_aic23_initialize(foo);
731
732         printk("AIC23 codec initialization done.\n");
733         return 0;
734 }
735 static int codec_stop(char *buf, char **start, off_t offset, int count,
736                       int *eof, void *data)
737 {
738         void *foo = NULL;
739
740         omap_aic23_shutdown(foo);
741
742         printk("AIC23 codec shutdown.\n");
743         return 0;
744 }
745 #endif /* CONFIG_PROC_FS */
746
747 module_init(audio_aic23_init);
748 module_exit(audio_aic23_exit);
749
750 MODULE_AUTHOR("Dirk Behme <dirk.behme@de.bosch.com>");
751 MODULE_DESCRIPTION("Glue audio driver for the TI AIC23 codec.");
752 MODULE_LICENSE("GPL");