]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/omap-audio-aic23.c
Merge current mainline tree into linux-omap tree
[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 #include <linux/mutex.h>
42
43 #include <asm/uaccess.h>
44 #include <mach/hardware.h>
45 #include <asm/io.h>
46 #include <asm/mach-types.h>
47
48 #include <mach/mcbsp.h>
49 #include <mach/fpga.h>
50 #include <mach/aic23.h>
51 #include <mach/clock.h>
52
53 #include "omap-audio.h"
54 #include "omap-audio-dma-intfc.h"
55
56 #ifdef CONFIG_PROC_FS
57 #include <linux/proc_fs.h>
58 #define PROC_START_FILE "driver/aic23-audio-start"
59 #define PROC_STOP_FILE  "driver/aic23-audio-stop"
60 #endif
61
62 //#define DEBUG
63
64 #ifdef DEBUG
65 #define DPRINTK(ARGS...)  printk("<%s>: ",__FUNCTION__);printk(ARGS)
66 #else
67 #define DPRINTK( x... )
68 #endif
69
70 #define CODEC_NAME               "AIC23"
71
72 #if CONFIG_MACH_OMAP_OSK
73 #define PLATFORM_NAME            "OMAP OSK"
74 #elif CONFIG_MACH_OMAP_INNOVATOR
75 #define PLATFORM_NAME            "OMAP INNOVATOR"
76 #else
77 #error "Unsupported plattform"
78 #endif
79
80 /* Define to set the AIC23 as the master w.r.t McBSP */
81 #define AIC23_MASTER
82
83 #define CODEC_CLOCK                   12000000
84
85 /*
86  * AUDIO related MACROS
87  */
88 #define DEFAULT_BITPERSAMPLE          16
89 #define AUDIO_RATE_DEFAULT            44100
90
91 /* Select the McBSP For Audio */
92 #define AUDIO_MCBSP                   OMAP_MCBSP1
93
94 #define REC_MASK                      (SOUND_MASK_LINE | SOUND_MASK_MIC)
95 #define DEV_MASK                      (REC_MASK | SOUND_MASK_VOLUME)
96
97 #define SET_VOLUME                    1
98 #define SET_LINE                      2
99
100 #define DEFAULT_OUTPUT_VOLUME         93
101 #define DEFAULT_INPUT_VOLUME          0 /* 0 ==> mute line in */
102
103 #define OUTPUT_VOLUME_MIN             LHV_MIN
104 #define OUTPUT_VOLUME_MAX             LHV_MAX
105 #define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
106 #define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
107
108 #define INPUT_VOLUME_MIN              LIV_MIN
109 #define INPUT_VOLUME_MAX              LIV_MAX
110 #define INPUT_VOLUME_RANGE            (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
111 #define INPUT_VOLUME_MASK             INPUT_VOLUME_MAX
112
113 #define NUMBER_SAMPLE_RATES_SUPPORTED 9
114
115 /*
116  * HW interface start and stop helper functions
117  */
118 static int audio_ifc_start(void)
119 {
120         omap_mcbsp_start(AUDIO_MCBSP);
121         return 0;
122 }
123
124 static int audio_ifc_stop(void)
125 {
126         omap_mcbsp_stop(AUDIO_MCBSP);
127         return 0;
128 }
129
130 static audio_stream_t output_stream = {
131         .id              = "AIC23 out",
132         .dma_dev         = OMAP_DMA_MCBSP1_TX,
133         .input_or_output = FMODE_WRITE,
134         .hw_start       = audio_ifc_start,
135         .hw_stop         = audio_ifc_stop
136 };
137
138 static audio_stream_t input_stream = {
139         .id              = "AIC23 in",
140         .dma_dev         = OMAP_DMA_MCBSP1_RX,
141         .input_or_output = FMODE_READ,
142         .hw_start       = audio_ifc_start,
143         .hw_stop         = audio_ifc_stop
144 };
145
146 static struct clk *aic23_mclk = 0;
147
148 static int audio_dev_id, mixer_dev_id;
149
150 static struct aic23_local_info {
151         u8  volume;
152         u16 volume_reg;
153         u8  line;
154         u8  mic;
155         u16 input_volume_reg;
156         int mod_cnt;
157 } aic23_local;
158
159 struct sample_rate_reg_info {
160         u32 sample_rate;
161         u8  control;            /* SR3, SR2, SR1, SR0 and BOSR */
162         u8  divider;            /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
163 };
164
165 /* To Store the default sample rate */
166 static long audio_samplerate = AUDIO_RATE_DEFAULT;
167
168 /* DAC USB-mode sampling rates (MCLK = 12 MHz) */
169 static const struct sample_rate_reg_info
170 reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
171         {96000, 0x0E, 0},
172         {88200, 0x1F, 0},
173         {48000, 0x00, 0},
174         {44100, 0x11, 0},
175         {32000, 0x0C, 0},
176         {24000, 0x00, 1},
177         {16000, 0x0C, 1},
178         { 8000, 0x06, 0},
179         { 4000, 0x06, 1},
180 };
181
182 static struct omap_mcbsp_reg_cfg initial_config = {
183         .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
184         .spcr1 = RINTM(3) | RRST,
185         .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
186         RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
187         .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
188         .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
189         XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
190         .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
191         .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
192         .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
193 #ifndef AIC23_MASTER
194         /* configure McBSP to be the I2S master */
195         .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
196 #else
197         /* configure McBSP to be the I2S slave */
198         .pcr0  = CLKXP | CLKRP,
199 #endif /* AIC23_MASTER */
200 };
201
202 static void omap_aic23_initialize(void *dummy);
203 static void omap_aic23_shutdown(void *dummy);
204 static int  omap_aic23_ioctl(struct inode *inode, struct file *file,
205                              uint cmd, ulong arg);
206 static int  omap_aic23_probe(void);
207 #ifdef MODULE
208 static void omap_aic23_remove(void);
209 #endif
210 static int  omap_aic23_suspend(void);
211 static int  omap_aic23_resume(void);
212 static inline void aic23_configure(void);
213 static int  mixer_open(struct inode *inode, struct file *file);
214 static int  mixer_release(struct inode *inode, struct file *file);
215 static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
216                         ulong arg);
217
218 #ifdef CONFIG_PROC_FS
219 static int codec_start(char *buf, char **start, off_t offset, int count,
220                        int *eof, void *data);
221 static int codec_stop(char *buf, char **start, off_t offset, int count,
222                       int *eof, void *data);
223 #endif
224
225
226 /* File Op structure for mixer */
227 static struct file_operations omap_mixer_fops = {
228         .open           = mixer_open,
229         .release        = mixer_release,
230         .ioctl          = mixer_ioctl,
231         .owner          = THIS_MODULE
232 };
233
234 /* To store characteristic info regarding the codec for the audio driver */
235 static audio_state_t aic23_state = {
236         .output_stream  = &output_stream,
237         .input_stream   = &input_stream,
238 /*      .need_tx_for_rx = 1, //Once the Full Duplex works  */
239         .need_tx_for_rx = 0,
240         .hw_init        = omap_aic23_initialize,
241         .hw_shutdown    = omap_aic23_shutdown,
242         .client_ioctl   = omap_aic23_ioctl,
243         .hw_probe       = omap_aic23_probe,
244         .hw_remove      =  __exit_p(omap_aic23_remove),
245         .hw_suspend     = omap_aic23_suspend,
246         .hw_resume      = omap_aic23_resume,
247 };
248
249 /* This will be defined in the audio.h */
250 static struct file_operations *omap_audio_fops;
251
252 extern int aic23_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         aic23_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         mutex_init(&aic23_state.mutex);
676
677         if (machine_is_omap_osk()) {
678                 /* Set MCLK to be clock input for AIC23 */
679                 aic23_mclk = clk_get(0, "mclk");
680             
681                 if(clk_get_rate( aic23_mclk) != CODEC_CLOCK){
682                         /* MCLK ist not at CODEC_CLOCK */
683                         if( clk_get_usecount(aic23_mclk) > 0 ){
684                                 /* MCLK is already in use */
685                                 printk(KERN_WARNING "MCLK in use at %d Hz. We change it to %d Hz\n",
686                                        (uint)clk_get_rate( aic23_mclk), CODEC_CLOCK);
687                         }
688                         if( clk_set_rate( aic23_mclk, CODEC_CLOCK ) ){
689                                 printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
690                                 return -ECANCELED;
691                         }
692                 }
693
694                 clk_enable( aic23_mclk );
695
696                 DPRINTK("MCLK = %d [%d], usecount = %d\n",(uint)clk_get_rate( aic23_mclk ), 
697                         CODEC_CLOCK, clk_get_usecount( aic23_mclk));
698         }
699
700         if (machine_is_omap_innovator()) {
701                 u8 fpga;
702                 /*
703                   Turn on chip select for CODEC (shared with touchscreen).  
704                   Don't turn it back off, in case touch screen needs it.
705                 */                           
706                 fpga = fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
707                 fpga |= 0x4;
708                 fpga_write(fpga, OMAP1510_FPGA_TOUCHSCREEN);
709         }
710
711         /* register the codec with the audio driver */
712         if ((err = audio_register_codec(&aic23_state))) {
713                 printk(KERN_ERR
714                        "Failed to register AIC23 driver with Audio OSS Driver\n");
715         }
716
717         return err;
718 }
719
720 static void __exit audio_aic23_exit(void)
721 {
722         (void)audio_unregister_codec(&aic23_state);
723         return;
724 }
725
726 #ifdef CONFIG_PROC_FS
727 static int codec_start(char *buf, char **start, off_t offset, int count,
728                        int *eof, void *data)
729 {
730         void *foo = NULL;
731
732         omap_aic23_initialize(foo);
733
734         printk("AIC23 codec initialization done.\n");
735         return 0;
736 }
737 static int codec_stop(char *buf, char **start, off_t offset, int count,
738                       int *eof, void *data)
739 {
740         void *foo = NULL;
741
742         omap_aic23_shutdown(foo);
743
744         printk("AIC23 codec shutdown.\n");
745         return 0;
746 }
747 #endif /* CONFIG_PROC_FS */
748
749 module_init(audio_aic23_init);
750 module_exit(audio_aic23_exit);
751
752 MODULE_AUTHOR("Dirk Behme <dirk.behme@de.bosch.com>");
753 MODULE_DESCRIPTION("Glue audio driver for the TI AIC23 codec.");
754 MODULE_LICENSE("GPL");