]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/omap-audio-tsc2101.c
[PATCH] ARM: OMAP: OSS: sem2mutex conversion
[linux-2.6-omap-h63xx.git] / sound / oss / omap-audio-tsc2101.c
1 /*
2  * linux/sound/oss/omap-audio-tsc2101.c
3  *
4  * Glue driver for TSC2101 for OMAP processors
5  *
6  * Copyright (C) 2004 Texas Instruments, Inc.
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * History:
17  *  -------
18  *  2004-08-12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms.
19  *  2004-09-14 Sriram Kannan - Added /proc support for asynchronous starting/stopping the codec
20  *              (without affecting the normal driver flow).
21  *  2004-11-04 Nishanth Menon - Support for power management
22  *  2004-11-07 Nishanth Menon - Support for Common TSC access b/w Touchscreen and audio drivers
23  */
24
25 /***************************** INCLUDES ************************************/
26
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/fs.h>
31 #include <linux/delay.h>
32 #include <linux/pm.h>
33 #include <linux/errno.h>
34 #include <linux/sound.h>
35 #include <linux/soundcard.h>
36 #include <linux/mutex.h>
37
38 #include <asm/uaccess.h>
39 #include <asm/hardware.h>
40 #include <asm/arch/dma.h>
41 #include <asm/io.h>
42 #include <asm/hardware.h>
43
44 #include <asm/arch/mux.h>
45 #include <asm/arch/io.h>
46 #include <asm/mach-types.h>
47
48 #include "omap-audio.h"
49 #include "omap-audio-dma-intfc.h"
50 #include <asm/arch/mcbsp.h>
51 #ifdef CONFIG_ARCH_OMAP16XX
52 #include <../drivers/ssi/omap-uwire.h>
53 #include <asm/arch/dsp_common.h>
54 #elif defined(CONFIG_ARCH_OMAP24XX)
55 #else
56 #error "Unsupported configuration"
57 #endif
58
59 #include <asm/hardware/tsc2101.h>
60 #include <../drivers/ssi/omap-tsc2101.h>
61
62 /***************************** MACROS ************************************/
63
64 #define PROC_SUPPORT
65
66 #ifdef PROC_SUPPORT
67 #include <linux/proc_fs.h>
68 #define PROC_START_FILE "driver/tsc2101-audio-start"
69 #define PROC_STOP_FILE  "driver/tsc2101-audio-stop"
70 #endif
71
72 #define CODEC_NAME               "TSC2101"
73
74 #ifdef CONFIG_ARCH_OMAP16XX
75 #define PLATFORM_NAME "OMAP16XX"
76 #elif defined(CONFIG_ARCH_OMAP24XX)
77 #define PLATFORM_NAME "OMAP2"
78 #endif
79
80 /* Define to set the tsc as the master w.r.t McBSP */
81 #define TSC_MASTER
82
83 /*
84  * AUDIO related MACROS
85  */
86 #define DEFAULT_BITPERSAMPLE          16
87 #define AUDIO_RATE_DEFAULT                44100
88 #define PAGE2_AUDIO_CODEC_REGISTERS   (2)
89 #define LEAVE_CS                                  0x80
90
91 /* Select the McBSP For Audio */
92 /* 16XX is MCBSP1 and 24XX is MCBSP2*/
93 /* see include/asm-arm/arch-omap/mcbsp.h */
94 #ifndef AUDIO_MCBSP
95 #error "UnSupported Configuration"
96 #endif
97
98 #define REC_MASK                                  (SOUND_MASK_LINE | SOUND_MASK_MIC)
99 #define DEV_MASK                                  (REC_MASK | SOUND_MASK_VOLUME)
100
101 #define SET_VOLUME                                1
102 #define SET_LINE                                  2
103 #define SET_MIC       3
104 #define SET_RECSRC            4
105
106 #define DEFAULT_VOLUME                93
107 #define DEFAULT_INPUT_VOLUME      20    /* An minimal volume */
108
109 /* Tsc Audio Specific */
110 #define NUMBER_SAMPLE_RATES_SUPPORTED 16
111 #define OUTPUT_VOLUME_MIN 0x7F
112 #define OUTPUT_VOLUME_MAX 0x32
113 #define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
114 #define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MIN
115 #define DEFAULT_VOLUME_LEVEL          OUTPUT_VOLUME_MAX
116
117 /* use input vol of 75 for 0dB gain */
118 #define INPUT_VOLUME_MIN                      0x0
119 #define INPUT_VOLUME_MAX         0x7D
120 #define INPUT_VOLUME_RANGE                    (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
121 #define INPUT_VOLUME_MASK                     INPUT_VOLUME_MAX
122
123 /*********** Debug Macros ********/
124 /* To Generate a rather shrill tone -test the entire path */
125 //#define TONE_GEN
126 /* To Generate a tone for each keyclick - test the tsc,spi paths*/
127 //#define TEST_KEYCLICK
128 /* To dump the tsc registers for debug */
129 //#define TSC_DUMP_REGISTERS
130
131 #ifdef DPRINTK
132 #undef DPRINTK
133 #endif
134 #undef DEBUG
135
136 //#define DEBUG
137 #ifdef DEBUG
138 #define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
139 #define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
140 #define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
141 #else
142 #define DPRINTK( x... )
143 #define FN_IN
144 #define FN_OUT(n)
145 #endif
146
147 /***************************** Data Structures **********************************/
148
149 static int audio_ifc_start(void)
150 {
151         omap_mcbsp_start(AUDIO_MCBSP);
152         return 0;
153 }
154
155 static int audio_ifc_stop(void)
156 {
157         omap_mcbsp_stop(AUDIO_MCBSP);
158         return 0;
159 }
160
161 static audio_stream_t output_stream = {
162         .id                     = "TSC2101 out",
163         .dma_dev                = AUDIO_DMA_TX,
164         .input_or_output        = FMODE_WRITE,
165         .hw_start               = audio_ifc_start,
166         .hw_stop                = audio_ifc_stop,
167 };
168
169 static audio_stream_t input_stream = {
170         .id                     = "TSC2101 in",
171         .dma_dev                = AUDIO_DMA_RX,
172         .input_or_output        = FMODE_READ,
173         .hw_start               = audio_ifc_start,
174         .hw_stop                = audio_ifc_stop,
175 };
176
177 static int audio_dev_id, mixer_dev_id;
178
179 typedef struct {
180         u8      volume;
181         u8      line;
182         u8      mic;
183         int     recsrc;
184         int     mod_cnt;
185 } tsc2101_local_info;
186
187 static tsc2101_local_info tsc2101_local = {
188         volume:         DEFAULT_VOLUME,
189         line:           DEFAULT_INPUT_VOLUME,
190         mic:            DEFAULT_INPUT_VOLUME,
191         recsrc:         SOUND_MASK_LINE,
192         mod_cnt:        0
193 };
194
195 struct sample_rate_reg_info {
196         u16 sample_rate;
197         u8  divisor;
198         u8  fs_44kHz;           /* if 0 48 khz, if 1 44.1 khz fsref */
199 };
200
201 /* To Store the default sample rate */
202 static long audio_samplerate = AUDIO_RATE_DEFAULT;
203
204 static const struct sample_rate_reg_info
205  reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
206         /* Div 1 */
207         {48000, 0, 0},
208         {44100, 0, 1},
209         /* Div 1.5 */
210         {32000, 1, 0},
211         {29400, 1, 1},
212         /* Div 2 */
213         {24000, 2, 0},
214         {22050, 2, 1},
215         /* Div 3 */
216         {16000, 3, 0},
217         {14700, 3, 1},
218         /* Div 4 */
219         {12000, 4, 0},
220         {11025, 4, 1},
221         /* Div 5 */
222         {9600, 5, 0},
223         {8820, 5, 1},
224         /* Div 5.5 */
225         {8727, 6, 0},
226         {8018, 6, 1},
227         /* Div 6 */
228         {8000, 7, 0},
229         {7350, 7, 1},
230 };
231
232 static struct omap_mcbsp_reg_cfg initial_config = {
233         .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
234         .spcr1 = RINTM(3) | RRST,
235         .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
236                  RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
237         .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
238         .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
239                  XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
240         .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
241         .srgr1 = FWID(15),
242         .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
243
244         /* platform specific initialization */
245 #ifdef CONFIG_MACH_OMAP_H2
246         .pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
247 #elif defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H4) || defined(CONFIG_MACH_OMAP_APOLLON)
248
249 #ifndef TSC_MASTER
250         .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
251 #else
252         .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
253 #endif                          /* tsc Master defs */
254
255 #endif                          /* platform specific inits */
256 };
257
258 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
259
260 static void omap_tsc2101_initialize(void *dummy);
261
262 static void omap_tsc2101_shutdown(void *dummy);
263
264 static int  omap_tsc2101_ioctl(struct inode *inode, struct file *file,
265                                uint cmd, ulong arg);
266
267 static int  omap_tsc2101_probe(void);
268
269 static void omap_tsc2101_remove(void);
270
271 static int  omap_tsc2101_suspend(void);
272
273 static int  omap_tsc2101_resume(void);
274
275 static void tsc2101_configure(void);
276
277 static int  mixer_open(struct inode *inode, struct file *file);
278
279 static int  mixer_release(struct inode *inode, struct file *file);
280
281 static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
282                         ulong arg);
283
284 #ifdef TEST_KEYCLICK
285 void tsc2101_testkeyclick(void);
286 #endif
287
288 #ifdef TONE_GEN
289 void toneGen(void);
290 #endif
291
292 #ifdef TSC_DUMP_REGISTERS
293 static void tsc2101_dumpRegisters(void);
294 #endif
295
296 #ifdef PROC_SUPPORT
297 static int codec_start(char *buf, char **start, off_t offset, int count,
298                        int *eof, void *data);
299
300 static int codec_stop(char *buf, char **start, off_t offset, int count,
301                       int *eof, void *data);
302
303 static void tsc2101_start(void);
304 #endif
305
306 /******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
307
308 /* File Op structure for mixer */
309 static struct file_operations omap_mixer_fops = {
310         .open           = mixer_open,
311         .release        = mixer_release,
312         .ioctl          = mixer_ioctl,
313         .owner          = THIS_MODULE
314 };
315
316 /* To store characteristic info regarding the codec for the audio driver */
317 static audio_state_t tsc2101_state = {
318         .output_stream  = &output_stream,
319         .input_stream   = &input_stream,
320 /*      .need_tx_for_rx = 1, //Once the Full Duplex works  */
321         .need_tx_for_rx = 0,
322         .hw_init        = omap_tsc2101_initialize,
323         .hw_shutdown    = omap_tsc2101_shutdown,
324         .client_ioctl   = omap_tsc2101_ioctl,
325         .hw_probe       = omap_tsc2101_probe,
326         .hw_remove      = omap_tsc2101_remove,
327         .hw_suspend     = omap_tsc2101_suspend,
328         .hw_resume      = omap_tsc2101_resume,
329         .mutex          = __MUTEX_INITIALIZER(tsc2101_state.mutex),
330 };
331
332 /* This will be defined in the Audio.h */
333 static struct file_operations *omap_audio_fops;
334
335 /***************************** MODULES SPECIFIC FUNCTIONs *******************************/
336
337 /*********************************************************************************
338  *
339  * Simplified write for tsc Audio
340  *
341  *********************************************************************************/
342 static __inline__ void audio_tsc2101_write(u8 address, u16 data)
343 {
344         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
345 }
346
347 /*********************************************************************************
348  *
349  * Simplified read for tsc  Audio
350  *
351  *********************************************************************************/
352 static __inline__ u16 audio_tsc2101_read(u8 address)
353 {
354         return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
355 }
356
357 /*********************************************************************************
358  *
359  * tsc2101_update()
360  * Volume Adj etc
361  *
362  ********************************************************************************/
363 static int tsc2101_update(int flag, int val)
364 {
365         u16 volume;
366         u16 data;
367
368         FN_IN;
369         switch (flag) {
370         case SET_VOLUME:
371                 if (val < 0 || val > 100) {
372                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
373                         return -EPERM;
374                 }
375                 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
376                 volume =
377                     ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
378                 /* invert the value for getting the proper range 0 min and 100 max */
379                 volume = OUTPUT_VOLUME_MIN - volume;
380                 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
381                 data &=
382                     ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
383                       DGC_DARVL(OUTPUT_VOLUME_MIN));
384                 data |= DGC_DALVL(volume) | DGC_DARVL(volume);
385                 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
386                 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
387
388                 break;
389
390         case SET_LINE:
391                 if (val < 0 || val > 100) {
392                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
393                         return -EPERM;
394                 }
395                 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
396                 /* NOTE: 0 is minimum volume and not mute */
397                 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
398                 /* Handset Input not muted, AGC for Handset In off */
399                 audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
400         HGC_ADPGA_HED(volume));
401                 break;
402
403         case SET_MIC:
404                 if (val < 0 || val > 100) {
405                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
406                         return -EPERM;
407                 }
408                 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
409                 /* NOTE: 0 is minimum volume and not mute */
410                 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
411                 /* Handset Input not muted, AGC for Handset In off */
412                 audio_tsc2101_write(TSC2101_HANDSET_GAIN_CTRL,
413         HNGC_ADPGA_HND(volume));
414                 break;
415
416         case SET_RECSRC:
417                 /*
418                  * If more than one recording device selected,
419                  * disable the device that is currently in use.
420                  */
421                 if (hweight32(val) > 1)
422                         val &= ~tsc2101_local.recsrc;
423
424                 data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
425                 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
426
427                 if (val == SOUND_MASK_MIC) {
428                         data |=  MPC_MICSEL(1);
429                         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
430                 }
431                 else if (val == SOUND_MASK_LINE) {
432                         data |=  MPC_MICSEL(0);
433                         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
434                 }
435                 else {
436                         printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
437          " value specified\n");
438                         return -EINVAL;
439                 }
440                 tsc2101_local.recsrc = val;
441                 break;
442         default:
443                 printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
444         "flag specified\n");
445                 break;
446         }
447
448         FN_OUT(0);
449         return 0;
450 }
451
452 /*********************************************************************************
453  *
454  * mixer_open()
455  *
456  ********************************************************************************/
457 static int mixer_open(struct inode *inode, struct file *file)
458 {
459         /* Any mixer specific initialization */
460
461         /* Initalize the tsc2101 */
462         omap_tsc2101_enable();
463
464         return 0;
465 }
466
467 /*********************************************************************************
468  *
469  * mixer_release()
470  *
471  ********************************************************************************/
472 static int mixer_release(struct inode *inode, struct file *file)
473 {
474         /* Any mixer specific Un-initialization */
475         omap_tsc2101_disable();
476
477         return 0;
478 }
479
480 /*********************************************************************************
481  *
482  * mixer_ioctl()
483  *
484  ********************************************************************************/
485 static int
486 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
487 {
488         int val;
489         int gain;
490         int ret = 0;
491         int nr = _IOC_NR(cmd);
492
493         /*
494          * We only accept mixer (type 'M') ioctls.
495          */
496         FN_IN;
497         if (_IOC_TYPE(cmd) != 'M')
498                 return -EINVAL;
499
500         DPRINTK(" 0x%08x\n", cmd);
501
502         if (cmd == SOUND_MIXER_INFO) {
503                 struct mixer_info mi;
504
505                 strncpy(mi.id, "TSC2101", sizeof(mi.id));
506                 strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
507                 mi.modify_counter = tsc2101_local.mod_cnt;
508                 FN_OUT(1);
509                 return copy_to_user((void __user *)arg, &mi, sizeof(mi));
510         }
511
512         if (_IOC_DIR(cmd) & _IOC_WRITE) {
513                 ret = get_user(val, (int __user *)arg);
514                 if (ret)
515                         goto out;
516
517                 /* Ignore separate left/right channel for now,
518                  * even the codec does support it.
519                  */
520                 gain = val & 255;
521
522                 switch (nr) {
523                 case SOUND_MIXER_VOLUME:
524                         tsc2101_local.volume = val;
525                         tsc2101_local.mod_cnt++;
526                         ret = tsc2101_update(SET_VOLUME, gain);
527                         break;
528
529                 case SOUND_MIXER_LINE:
530                         tsc2101_local.line = val;
531                         tsc2101_local.mod_cnt++;
532                         ret = tsc2101_update(SET_LINE, gain);
533                         break;
534
535                 case SOUND_MIXER_MIC:
536                         tsc2101_local.mic = val;
537                         tsc2101_local.mod_cnt++;
538                         ret = tsc2101_update(SET_MIC, gain);
539                         break;
540
541                 case SOUND_MIXER_RECSRC:
542                         if ((val & SOUND_MASK_LINE) ||
543                             (val & SOUND_MASK_MIC)) {
544                                 if (tsc2101_local.recsrc != val) {
545                                         tsc2101_local.mod_cnt++;
546                                         tsc2101_update(SET_RECSRC, val);
547                                 }
548                         }
549                         else {
550                                 ret = -EINVAL;
551                         }
552                         break;
553
554                 default:
555                         ret = -EINVAL;
556                 }
557         }
558
559         if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
560                 ret = 0;
561
562                 switch (nr) {
563                 case SOUND_MIXER_VOLUME:
564                         val = tsc2101_local.volume;
565                         val = (tsc2101_local.volume << 8) |
566           tsc2101_local.volume;
567                         break;
568                 case SOUND_MIXER_LINE:
569                         val = (tsc2101_local.line << 8) |
570           tsc2101_local.line;
571                         break;
572                 case SOUND_MIXER_MIC:
573                         val = (tsc2101_local.mic << 8) |
574           tsc2101_local.mic;
575                         break;
576                 case SOUND_MIXER_RECSRC:
577                         val = tsc2101_local.recsrc;
578                         break;
579                 case SOUND_MIXER_RECMASK:
580                         val = REC_MASK;
581                         break;
582                 case SOUND_MIXER_DEVMASK:
583                         val = DEV_MASK;
584                         break;
585                 case SOUND_MIXER_CAPS:
586                         val = 0;
587                         break;
588                 case SOUND_MIXER_STEREODEVS:
589                         val = SOUND_MASK_VOLUME;
590                         break;
591                 default:
592                         val = 0;
593                         printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
594          "read ioctl flag specified\n");
595                         ret = -EINVAL;
596                         break;
597                 }
598
599                 if (ret == 0)
600                         ret = put_user(val, (int __user *)arg);
601         }
602       out:
603         FN_OUT(0);
604         return ret;
605
606 }
607
608 /*********************************************************************************
609  *
610  * omap_set_samplerate()
611  *
612  ********************************************************************************/
613 static int omap_set_samplerate(long sample_rate)
614 {
615         u8 count = 0;
616         u16 data = 0;
617         int clkgdv = 0;
618         /* wait for any frame to complete */
619         udelay(125);
620
621         /* Search for the right sample rate */
622         while ((reg_info[count].sample_rate != sample_rate) &&
623                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
624                 count++;
625         }
626         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
627                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
628                        (int)sample_rate);
629                 return -EPERM;
630         }
631
632         /* Set AC1 */
633         data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
634         /*Clear prev settings */
635         data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
636         data |=
637             AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
638                                                            divisor);
639         audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
640
641         /* Set the AC3 */
642         data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
643         /*Clear prev settings */
644         data &= ~(AC3_REFFS | AC3_SLVMS);
645         data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
646 #ifdef TSC_MASTER
647         data |= AC3_SLVMS;
648 #endif                          /* #ifdef TSC_MASTER */
649         audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
650
651         /* program the PLLs */
652         if (reg_info[count].fs_44kHz) {
653                 /* 44.1 khz - 12 MHz Mclk */
654                 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));    /* PVAL 1; I_VAL 7 */
655                 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
656         } else {
657                 /* 48 khz - 12 Mhz Mclk */
658                 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));    /* PVAL 1; I_VAL 8 */
659                 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
660         }
661
662         audio_samplerate = sample_rate;
663
664         /* Set the sample rate */
665 #ifndef TSC_MASTER
666         clkgdv =
667             DEFAULT_MCBSP_CLOCK / (sample_rate *
668                                    (DEFAULT_BITPERSAMPLE * 2 - 1));
669         if (clkgdv)
670                 initial_config.srgr1 =
671                     (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
672         else
673                 return (1);
674
675         /* Stereo Mode */
676         initial_config.srgr2 =
677             (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
678 #else
679         initial_config.srgr1 =
680             (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
681         initial_config.srgr2 =
682             ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
683
684 #endif                          /* end of #ifdef TSC_MASTER */
685         omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
686
687         return 0;
688 }
689
690 /*********************************************************************************
691  *
692  * omap_tsc2101_initialize() [hw_init() ]
693  *
694  ********************************************************************************/
695 static void omap_tsc2101_initialize(void *dummy)
696 {
697
698         DPRINTK("omap_tsc2101_initialize entry\n");
699
700         /* initialize with default sample rate */
701         audio_samplerate = AUDIO_RATE_DEFAULT;
702
703         omap_mcbsp_request(AUDIO_MCBSP);
704
705         /* if configured, then stop mcbsp */
706         omap_mcbsp_stop(AUDIO_MCBSP);
707
708         omap_tsc2101_enable();
709
710         omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
711         omap_mcbsp_start(AUDIO_MCBSP);
712         tsc2101_configure();
713
714 #ifdef TEST_KEYCLICK
715         tsc2101_testkeyclick();
716 #endif
717
718 #ifdef TONE_GEN
719         toneGen();
720 #endif
721
722         DPRINTK("omap_tsc2101_initialize exit\n");
723 }
724
725 /*********************************************************************************
726  *
727  * omap_tsc2101_shutdown() [hw_shutdown() ]
728  *
729  ********************************************************************************/
730 static void omap_tsc2101_shutdown(void *dummy)
731 {
732         /*
733            Turn off codec after it is done.
734            Can't do it immediately, since it may still have
735            buffered data.
736
737            Wait 20ms (arbitrary value) and then turn it off.
738          */
739
740         FN_IN;
741         set_current_state(TASK_INTERRUPTIBLE);
742         schedule_timeout(2);
743
744         omap_mcbsp_stop(AUDIO_MCBSP);
745         omap_mcbsp_free(AUDIO_MCBSP);
746
747         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
748                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
749
750         omap_tsc2101_disable();
751
752         FN_OUT(0);
753 }
754
755 /*********************************************************************************
756  *
757  * tsc2101_configure
758  *
759  ********************************************************************************/
760 static void tsc2101_configure(void)
761 {
762         FN_IN;
763
764         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
765
766         /*Mute Analog Sidetone */
767         /*Select MIC_INHED input for headset */
768         /*Cell Phone In not connected */
769         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
770                             MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
771
772         /* Set record source */
773         tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
774
775         /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
776         /* 1dB AGC hysteresis */
777         /* MICes bias 2V */
778         audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
779
780         /* Set codec output volume */
781         audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
782
783         /* DAC left and right routed to SPK2 */
784         /* SPK1/2 unmuted */
785         audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
786                             AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
787                             AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
788                             AC5_HDSCPTC);
789
790         /* OUT8P/N muted, CPOUT muted */
791
792         audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
793                             AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
794                             AC6_VGNDSCPTC);
795
796         /* Headset/Hook switch detect disabled */
797         audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
798
799         /* Left line input volume control */
800         tsc2101_update(SET_LINE, tsc2101_local.line);
801
802         /* mic input volume control */
803         tsc2101_update(SET_MIC, tsc2101_local.mic);
804
805         /* Left/Right headphone channel volume control */
806         /* Zero-cross detect on */
807         tsc2101_update(SET_VOLUME, tsc2101_local.volume);
808
809         /* clock configuration */
810         omap_set_samplerate(audio_samplerate);
811
812 #ifdef TSC_DUMP_REGISTERS
813         tsc2101_dumpRegisters();
814 #endif
815
816         FN_OUT(0);
817 }
818
819 #ifdef PROC_SUPPORT
820 static void tsc2101_start(void)
821 {
822         FN_IN;
823
824         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
825
826         /*Mute Analog Sidetone */
827         /*Select MIC_INHED input for headset */
828         /*Cell Phone In not connected */
829         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
830                             MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
831
832         /* Set record source */
833         tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
834
835         /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
836         /* 1dB AGC hysteresis */
837         /* MICes bias 2V */
838         audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
839
840         /* Set codec output volume */
841         audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
842
843         /* DAC left and right routed to SPK2 */
844         /* SPK1/2 unmuted */
845         audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
846                             AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
847                             AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
848                             AC5_HDSCPTC);
849
850         /* OUT8P/N muted, CPOUT muted */
851
852         audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
853                             AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
854                             AC6_VGNDSCPTC);
855
856         /* Headset/Hook switch detect disabled */
857         audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
858
859         /* Left line input volume control */
860         tsc2101_update(SET_LINE, tsc2101_local.line);
861
862         /* mic input volume control */
863         tsc2101_update(SET_MIC, tsc2101_local.mic);
864
865         /* Left/Right headphone channel volume control */
866         /* Zero-cross detect on */
867         tsc2101_update(SET_VOLUME, tsc2101_local.volume);
868
869         FN_OUT(0);
870
871 }
872 #endif
873
874 /******************************************************************************************
875  *
876  * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
877  * routine handles some platform specific ioctl's
878  *
879  ******************************************************************************************/
880 static int
881 omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
882 {
883         long val;
884         int ret = 0;
885
886         DPRINTK(" 0x%08x\n", cmd);
887
888         /*
889          * These are platform dependent ioctls which are not handled by the
890          * generic omap-audio module.
891          */
892         switch (cmd) {
893         case SNDCTL_DSP_STEREO:
894                 ret = get_user(val, (int __user *)arg);
895                 if (ret)
896                         return ret;
897                 /* the AIC23 is stereo only */
898                 ret = (val == 0) ? -EINVAL : 1;
899                 FN_OUT(1);
900                 return put_user(ret, (int __user *)arg);
901
902         case SNDCTL_DSP_CHANNELS:
903         case SOUND_PCM_READ_CHANNELS:
904                 /* the AIC23 is stereo only */
905                 FN_OUT(2);
906                 return put_user(2, (long __user *)arg);
907
908         case SNDCTL_DSP_SPEED:
909                 ret = get_user(val, (long __user *)arg);
910                 if (ret)
911                         break;
912                 ret = omap_set_samplerate(val);
913                 if (ret)
914                         break;
915                 /* fall through */
916
917         case SOUND_PCM_READ_RATE:
918                 FN_OUT(3);
919                 return put_user(audio_samplerate, (long __user *)arg);
920
921         case SOUND_PCM_READ_BITS:
922         case SNDCTL_DSP_SETFMT:
923         case SNDCTL_DSP_GETFMTS:
924                 /* we can do 16-bit only */
925                 FN_OUT(4);
926                 return put_user(AFMT_S16_LE, (long __user *)arg);
927
928         default:
929                 /* Maybe this is meant for the mixer (As per OSS Docs) */
930                 FN_OUT(5);
931                 return mixer_ioctl(inode, file, cmd, arg);
932         }
933
934         FN_OUT(0);
935         return ret;
936 }
937
938 /*********************************************************************************
939  *
940  * module_probe for TSC2101
941  *
942  ********************************************************************************/
943 static int omap_tsc2101_probe(void)
944 {
945         FN_IN;
946
947         /* Get the fops from audio oss driver */
948         if (!(omap_audio_fops = audio_get_fops())) {
949                 printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
950                 audio_unregister_codec(&tsc2101_state);
951                 return -EPERM;
952         }
953
954         /* register devices */
955         audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
956         mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
957
958 #ifdef PROC_SUPPORT
959         create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
960                                NULL /* parent dir */ ,
961                                codec_start, NULL /* client data */ );
962
963         create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
964                                NULL /* parent dir */ ,
965                                codec_stop, NULL /* client data */ );
966 #endif
967
968         /* Announcement Time */
969         printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
970                " Audio support initialized\n");
971
972         FN_OUT(0);
973         return 0;
974 }
975
976 /*********************************************************************************
977  *
978  * Module Remove for TSC2101
979  *
980  ********************************************************************************/
981 static void omap_tsc2101_remove(void)
982 {
983         FN_IN;
984         /* Un-Register the codec with the audio driver */
985         unregister_sound_dsp(audio_dev_id);
986         unregister_sound_mixer(mixer_dev_id);
987
988 #ifdef PROC_SUPPORT
989         remove_proc_entry(PROC_START_FILE, NULL);
990         remove_proc_entry(PROC_STOP_FILE, NULL);
991 #endif
992         FN_OUT(0);
993
994 }
995
996 /*********************************************************************************
997  *
998  * Module Suspend for TSC2101
999  *
1000  ********************************************************************************/
1001 static int omap_tsc2101_suspend(void)
1002 {
1003
1004         FN_OUT(0);
1005         return 0;
1006 }
1007
1008 /*********************************************************************************
1009  *
1010  * Module Resume for TSC2101
1011  *
1012  ********************************************************************************/
1013 static int omap_tsc2101_resume(void)
1014 {
1015
1016         FN_OUT(0);
1017         return 0;
1018 }
1019
1020 /*********************************************************************************
1021  *
1022  * module_init for TSC2101
1023  *
1024  ********************************************************************************/
1025 static int __init audio_tsc2101_init(void)
1026 {
1027
1028         int err = 0;
1029         FN_IN;
1030
1031         if (machine_is_omap_osk() || machine_is_omap_innovator())
1032                 return -ENODEV;
1033
1034         /* register the codec with the audio driver */
1035         if ((err = audio_register_codec(&tsc2101_state))) {
1036                 printk(KERN_ERR
1037                        "Failed to register TSC driver with Audio OSS Driver\n");
1038         }
1039         FN_OUT(err);
1040         return err;
1041 }
1042
1043 /*********************************************************************************
1044  *
1045  * module_exit for TSC2101
1046  *
1047  ********************************************************************************/
1048 static void __exit audio_tsc2101_exit(void)
1049 {
1050
1051         FN_IN;
1052         (void)audio_unregister_codec(&tsc2101_state);
1053         FN_OUT(0);
1054         return;
1055 }
1056
1057 /**************************** DEBUG FUNCTIONS ***********************************/
1058
1059 /*********************************************************************************
1060  * TEST_KEYCLICK:
1061  * This is a test to generate various keyclick sound on tsc.
1062  * verifies if the tsc and the spi interfaces are operational.
1063  *
1064  ********************************************************************************/
1065 #ifdef TEST_KEYCLICK
1066 void tsc2101_testkeyclick(void)
1067 {
1068         u8 freq = 0;
1069         u16 old_reg_val, reg_val;
1070         u32 uDummyVal = 0;
1071         u32 uTryVal = 0;
1072
1073         old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
1074
1075         /* Keyclick active, max amplitude and longest key click len(32 period) */
1076         printk(KERN_INFO " TESTING KEYCLICK\n Listen carefully NOW....\n");
1077         printk(KERN_INFO " OLD REG VAL=0x%x\n", old_reg_val);
1078         /* try all frequencies */
1079         for (; freq < 8; freq++) {
1080                 /* Keyclick active, max amplitude and longest key click len(32 period) */
1081                 reg_val = old_reg_val | AC2_KCLAC(0x7) | AC2_KCLLN(0xF);
1082                 uDummyVal = 0;
1083                 uTryVal = 0;
1084                 printk(KERN_INFO "\n\nTrying frequency %d reg val= 0x%x\n",
1085                        freq, reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1086                 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2,
1087                                     reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1088                 printk("DONE. Wait 10 ms ...\n");
1089                 /* wait till the kclk bit is auto cleared! time out also to be considered. */
1090                 while (audio_tsc2101_read(TSC2101_AUDIO_CTRL_2) & AC2_KCLEN) {
1091                         udelay(3);
1092                         uTryVal++;
1093                         if (uTryVal > 2000) {
1094                                 printk(KERN_ERR
1095                                        "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
1096                                        freq);
1097                                 printk(KERN_INFO
1098                                        "uTryVal == %d: Read back new reg val= 0x%x\n",
1099                                        uTryVal,
1100                                        audio_tsc2101_read
1101                                        (TSC2101_AUDIO_CTRL_2));
1102                                 /* clear */
1103                                 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
1104                                 break;
1105                         }
1106                 }
1107         }
1108         /* put the old value back */
1109         audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, old_reg_val);
1110         printk(KERN_INFO " KEYCLICK TEST COMPLETE\n");
1111
1112 }                               /* End of tsc2101_testkeyclick */
1113
1114 #endif                          /* TEST_KEYCLICK */
1115
1116 /*********************************************************************************
1117  * TONEGEN:
1118  * This is a test to generate a rather unpleasant sound..
1119  * verifies if the mcbsp is active (requires MCBSP_DIRECT_RW to be active on McBSP)
1120  *
1121  ********************************************************************************/
1122 #ifdef TONE_GEN
1123 /* Generates a shrill tone */
1124 u16 tone[] = {
1125         0x0ce4, 0x0ce4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1126         0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1127         0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1128         0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1129         0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1130         0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1131         0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1132         0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1133         0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1134         0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1135         0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1136         0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1137         0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1138         0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1139         0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1140         0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1141         0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1142         0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1143         0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1144         0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1145         0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1146         0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1147         0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1148         0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1149         0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1150         0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1151         0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1152         0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1153         0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1154         0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1155         0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1156         0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1157         0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000
1158 };
1159
1160 void toneGen(void)
1161 {
1162         int count = 0;
1163         int ret = 0;
1164         printk(KERN_INFO "TONE GEN TEST :");
1165
1166         for (count = 0; count < 5000; count++) {
1167                 int bytes;
1168                 for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
1169                         ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
1170                         if (ret == -1) {
1171                                 /* retry */
1172                                 bytes--;
1173                         } else if (ret == -2) {
1174                                 printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
1175                                 return;
1176                         }
1177                 }
1178         }
1179         printk(KERN_INFO "SUCCESS\n");
1180 }
1181
1182 #endif                          /* End of TONE_GEN */
1183
1184 /*********************************************************************************
1185  *
1186  * TSC_DUMP_REGISTERS:
1187  * This will dump the entire register set of Page 2 tsc2101. 
1188  * Useful for major goof ups
1189  *
1190  ********************************************************************************/
1191 #ifdef TSC_DUMP_REGISTERS
1192 static void tsc2101_dumpRegisters(void)
1193 {
1194         int i = 0;
1195         u16 data = 0;
1196         printk("TSC 2101 Register dump for Page 2 \n");
1197         for (i = 0; i < 0x27; i++) {
1198                 data = audio_tsc2101_read(i);
1199                 printk(KERN_INFO "Register[%x]=0x%04x\n", i, data);
1200
1201         }
1202 }
1203 #endif                          /* End of #ifdef TSC_DUMP_REGISTERS */
1204
1205 #ifdef PROC_SUPPORT
1206 static int codec_start(char *buf, char **start, off_t offset, int count,
1207                        int *eof, void *data)
1208 {
1209         omap_tsc2101_enable();
1210         tsc2101_start();
1211         printk("Codec initialization done.\n");
1212         return 0;
1213 }
1214 static int codec_stop(char *buf, char **start, off_t offset, int count,
1215                       int *eof, void *data)
1216 {
1217
1218         omap_tsc2101_disable();
1219         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
1220                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
1221         printk("Codec shutdown.\n");
1222         return 0;
1223 }
1224 #endif
1225
1226 /*********************************************************************************
1227  *
1228  * Other misc management, registration etc
1229  *
1230  ********************************************************************************/
1231 module_init(audio_tsc2101_init);
1232 module_exit(audio_tsc2101_exit);
1233
1234 MODULE_AUTHOR("Texas Instruments");
1235 MODULE_DESCRIPTION
1236     ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
1237 MODULE_LICENSE("GPL");