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