]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/omap-audio-tsc2101.c
ARM: OMAP: Clean up header file duplication
[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 <mach/hardware.h>
40 #include <mach/dma.h>
41 #include <asm/io.h>
42
43 #include <mach/mux.h>
44 #include <mach/io.h>
45 #include <asm/mach-types.h>
46
47 #include "omap-audio.h"
48 #include "omap-audio-dma-intfc.h"
49 #include <mach/mcbsp.h>
50 #ifdef CONFIG_ARCH_OMAP16XX
51 #include <../drivers/ssi/omap-uwire.h>
52 #include <mach/dsp_common.h>
53 #elif defined(CONFIG_ARCH_OMAP24XX)
54 #else
55 #error "Unsupported configuration"
56 #endif
57
58 #include <asm/hardware/tsc2101.h>
59 #include <../drivers/ssi/omap-tsc2101.h>
60
61 /***************************** MACROS ************************************/
62
63 #define PROC_SUPPORT
64
65 #ifdef PROC_SUPPORT
66 #include <linux/proc_fs.h>
67 #define PROC_START_FILE "driver/tsc2101-audio-start"
68 #define PROC_STOP_FILE  "driver/tsc2101-audio-stop"
69 #endif
70
71 #define CODEC_NAME               "TSC2101"
72
73 #ifdef CONFIG_ARCH_OMAP16XX
74 #define PLATFORM_NAME "OMAP16XX"
75 #elif defined(CONFIG_ARCH_OMAP24XX)
76 #define PLATFORM_NAME "OMAP2"
77 #endif
78
79 /* Define to set the tsc as the master w.r.t McBSP */
80 #define TSC_MASTER
81
82 /*
83  * AUDIO related MACROS
84  */
85 #define DEFAULT_BITPERSAMPLE          16
86 #define AUDIO_RATE_DEFAULT                44100
87 #define PAGE2_AUDIO_CODEC_REGISTERS   (2)
88 #define LEAVE_CS                                  0x80
89
90 /* Select the McBSP For Audio */
91 /* 16XX is MCBSP1 and 24XX is MCBSP2*/
92 /* see include/asm-arm/arch-omap/mcbsp.h */
93 #ifndef AUDIO_MCBSP
94 #error "UnSupported Configuration"
95 #endif
96
97 #define REC_MASK                                  (SOUND_MASK_LINE | SOUND_MASK_MIC)
98 #define DEV_MASK                                  (REC_MASK | SOUND_MASK_VOLUME)
99
100 #define SET_VOLUME                                1
101 #define SET_LINE                                  2
102 #define SET_MIC       3
103 #define SET_RECSRC            4
104
105 #define DEFAULT_VOLUME                93
106 #define DEFAULT_INPUT_VOLUME      20    /* An minimal volume */
107
108 /* Tsc Audio Specific */
109 #define NUMBER_SAMPLE_RATES_SUPPORTED 16
110 #define OUTPUT_VOLUME_MIN 0x7F
111 #define OUTPUT_VOLUME_MAX 0x32
112 #define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
113 #define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MIN
114 #define DEFAULT_VOLUME_LEVEL          OUTPUT_VOLUME_MAX
115
116 /* use input vol of 75 for 0dB gain */
117 #define INPUT_VOLUME_MIN                      0x0
118 #define INPUT_VOLUME_MAX         0x7D
119 #define INPUT_VOLUME_RANGE                    (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
120 #define INPUT_VOLUME_MASK                     INPUT_VOLUME_MAX
121
122 /*********** Debug Macros ********/
123 /* To Generate a rather shrill tone -test the entire path */
124 //#define TONE_GEN
125 /* To Generate a tone for each keyclick - test the tsc,spi paths*/
126 //#define TEST_KEYCLICK
127 /* To dump the tsc registers for debug */
128 //#define TSC_DUMP_REGISTERS
129
130 #ifdef DPRINTK
131 #undef DPRINTK
132 #endif
133 #undef DEBUG
134
135 //#define DEBUG
136 #ifdef DEBUG
137 #define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
138 #define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
139 #define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
140 #else
141 #define DPRINTK( x... )
142 #define FN_IN
143 #define FN_OUT(n)
144 #endif
145
146 /***************************** Data Structures **********************************/
147
148 static int audio_ifc_start(void)
149 {
150         omap_mcbsp_start(AUDIO_MCBSP);
151         return 0;
152 }
153
154 static int audio_ifc_stop(void)
155 {
156         omap_mcbsp_stop(AUDIO_MCBSP);
157         return 0;
158 }
159
160 static audio_stream_t output_stream = {
161         .id                     = "TSC2101 out",
162         .dma_dev                = AUDIO_DMA_TX,
163         .input_or_output        = FMODE_WRITE,
164         .hw_start               = audio_ifc_start,
165         .hw_stop                = audio_ifc_stop,
166 };
167
168 static audio_stream_t input_stream = {
169         .id                     = "TSC2101 in",
170         .dma_dev                = AUDIO_DMA_RX,
171         .input_or_output        = FMODE_READ,
172         .hw_start               = audio_ifc_start,
173         .hw_stop                = audio_ifc_stop,
174 };
175
176 static int audio_dev_id, mixer_dev_id;
177
178 typedef struct {
179         u8      volume;
180         u8      line;
181         u8      mic;
182         int     recsrc;
183         int     mod_cnt;
184 } tsc2101_local_info;
185
186 static tsc2101_local_info tsc2101_local = {
187         volume:         DEFAULT_VOLUME,
188         line:           DEFAULT_INPUT_VOLUME,
189         mic:            DEFAULT_INPUT_VOLUME,
190         recsrc:         SOUND_MASK_LINE,
191         mod_cnt:        0
192 };
193
194 struct sample_rate_reg_info {
195         u16 sample_rate;
196         u8  divisor;
197         u8  fs_44kHz;           /* if 0 48 khz, if 1 44.1 khz fsref */
198 };
199
200 /* To Store the default sample rate */
201 static long audio_samplerate = AUDIO_RATE_DEFAULT;
202
203 static const struct sample_rate_reg_info
204  reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
205         /* Div 1 */
206         {48000, 0, 0},
207         {44100, 0, 1},
208         /* Div 1.5 */
209         {32000, 1, 0},
210         {29400, 1, 1},
211         /* Div 2 */
212         {24000, 2, 0},
213         {22050, 2, 1},
214         /* Div 3 */
215         {16000, 3, 0},
216         {14700, 3, 1},
217         /* Div 4 */
218         {12000, 4, 0},
219         {11025, 4, 1},
220         /* Div 5 */
221         {9600, 5, 0},
222         {8820, 5, 1},
223         /* Div 5.5 */
224         {8727, 6, 0},
225         {8018, 6, 1},
226         /* Div 6 */
227         {8000, 7, 0},
228         {7350, 7, 1},
229 };
230
231 static struct omap_mcbsp_reg_cfg initial_config = {
232         .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
233         .spcr1 = RINTM(3) | RRST,
234         .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
235                  RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
236         .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
237         .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
238                  XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
239         .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
240         .srgr1 = FWID(15),
241         .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
242
243         /* platform specific initialization */
244 #ifdef CONFIG_MACH_OMAP_H2
245         .pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
246 #elif defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H4) || defined(CONFIG_MACH_OMAP_APOLLON)
247
248 #ifndef TSC_MASTER
249         .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
250 #else
251         .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
252 #endif                          /* tsc Master defs */
253
254 #endif                          /* platform specific inits */
255 };
256
257 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
258
259 static void omap_tsc2101_initialize(void *dummy);
260
261 static void omap_tsc2101_shutdown(void *dummy);
262
263 static int  omap_tsc2101_ioctl(struct inode *inode, struct file *file,
264                                uint cmd, ulong arg);
265
266 static int  omap_tsc2101_probe(void);
267
268 static void omap_tsc2101_remove(void);
269
270 static int  omap_tsc2101_suspend(void);
271
272 static int  omap_tsc2101_resume(void);
273
274 static void tsc2101_configure(void);
275
276 static int  mixer_open(struct inode *inode, struct file *file);
277
278 static int  mixer_release(struct inode *inode, struct file *file);
279
280 static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
281                         ulong arg);
282
283 #ifdef TEST_KEYCLICK
284 void tsc2101_testkeyclick(void);
285 #endif
286
287 #ifdef TONE_GEN
288 void toneGen(void);
289 #endif
290
291 #ifdef TSC_DUMP_REGISTERS
292 static void tsc2101_dumpRegisters(void);
293 #endif
294
295 #ifdef PROC_SUPPORT
296 static int codec_start(char *buf, char **start, off_t offset, int count,
297                        int *eof, void *data);
298
299 static int codec_stop(char *buf, char **start, off_t offset, int count,
300                       int *eof, void *data);
301
302 static void tsc2101_start(void);
303 #endif
304
305 /******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
306
307 /* File Op structure for mixer */
308 static struct file_operations omap_mixer_fops = {
309         .open           = mixer_open,
310         .release        = mixer_release,
311         .ioctl          = mixer_ioctl,
312         .owner          = THIS_MODULE
313 };
314
315 /* To store characteristic info regarding the codec for the audio driver */
316 static audio_state_t tsc2101_state = {
317         .output_stream  = &output_stream,
318         .input_stream   = &input_stream,
319 /*      .need_tx_for_rx = 1, //Once the Full Duplex works  */
320         .need_tx_for_rx = 0,
321         .hw_init        = omap_tsc2101_initialize,
322         .hw_shutdown    = omap_tsc2101_shutdown,
323         .client_ioctl   = omap_tsc2101_ioctl,
324         .hw_probe       = omap_tsc2101_probe,
325         .hw_remove      = omap_tsc2101_remove,
326         .hw_suspend     = omap_tsc2101_suspend,
327         .hw_resume      = omap_tsc2101_resume,
328 };
329
330 /* This will be defined in the Audio.h */
331 static struct file_operations *omap_audio_fops;
332
333 /***************************** MODULES SPECIFIC FUNCTIONs *******************************/
334
335 /*********************************************************************************
336  *
337  * Simplified write for tsc Audio
338  *
339  *********************************************************************************/
340 static __inline__ void audio_tsc2101_write(u8 address, u16 data)
341 {
342         omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
343 }
344
345 /*********************************************************************************
346  *
347  * Simplified read for tsc  Audio
348  *
349  *********************************************************************************/
350 static __inline__ u16 audio_tsc2101_read(u8 address)
351 {
352         return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
353 }
354
355 /*********************************************************************************
356  *
357  * tsc2101_update()
358  * Volume Adj etc
359  *
360  ********************************************************************************/
361 static int tsc2101_update(int flag, int val)
362 {
363         u16 volume;
364         u16 data;
365
366         FN_IN;
367         switch (flag) {
368         case SET_VOLUME:
369                 if (val < 0 || val > 100) {
370                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
371                         return -EPERM;
372                 }
373                 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
374                 volume =
375                     ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
376                 /* invert the value for getting the proper range 0 min and 100 max */
377                 volume = OUTPUT_VOLUME_MIN - volume;
378                 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
379                 data &=
380                     ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
381                       DGC_DARVL(OUTPUT_VOLUME_MIN));
382                 data |= DGC_DALVL(volume) | DGC_DARVL(volume);
383                 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
384                 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
385
386                 break;
387
388         case SET_LINE:
389                 if (val < 0 || val > 100) {
390                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
391                         return -EPERM;
392                 }
393                 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
394                 /* NOTE: 0 is minimum volume and not mute */
395                 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
396                 /* Handset Input not muted, AGC for Handset In off */
397                 audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
398         HGC_ADPGA_HED(volume));
399                 break;
400
401         case SET_MIC:
402                 if (val < 0 || val > 100) {
403                         printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
404                         return -EPERM;
405                 }
406                 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
407                 /* NOTE: 0 is minimum volume and not mute */
408                 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
409                 /* Handset Input not muted, AGC for Handset In off */
410                 audio_tsc2101_write(TSC2101_HANDSET_GAIN_CTRL,
411         HNGC_ADPGA_HND(volume));
412                 break;
413
414         case SET_RECSRC:
415                 /*
416                  * If more than one recording device selected,
417                  * disable the device that is currently in use.
418                  */
419                 if (hweight32(val) > 1)
420                         val &= ~tsc2101_local.recsrc;
421
422                 data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
423                 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
424
425                 if (val == SOUND_MASK_MIC) {
426                         data |=  MPC_MICSEL(1);
427                         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
428                 }
429                 else if (val == SOUND_MASK_LINE) {
430                         data |=  MPC_MICSEL(0);
431                         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
432                 }
433                 else {
434                         printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
435          " value specified\n");
436                         return -EINVAL;
437                 }
438                 tsc2101_local.recsrc = val;
439                 break;
440         default:
441                 printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
442         "flag specified\n");
443                 break;
444         }
445
446         FN_OUT(0);
447         return 0;
448 }
449
450 /*********************************************************************************
451  *
452  * mixer_open()
453  *
454  ********************************************************************************/
455 static int mixer_open(struct inode *inode, struct file *file)
456 {
457         /* Any mixer specific initialization */
458
459         /* Initalize the tsc2101 */
460         omap_tsc2101_enable();
461
462         return 0;
463 }
464
465 /*********************************************************************************
466  *
467  * mixer_release()
468  *
469  ********************************************************************************/
470 static int mixer_release(struct inode *inode, struct file *file)
471 {
472         /* Any mixer specific Un-initialization */
473         omap_tsc2101_disable();
474
475         return 0;
476 }
477
478 /*********************************************************************************
479  *
480  * mixer_ioctl()
481  *
482  ********************************************************************************/
483 static int
484 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
485 {
486         int val;
487         int gain;
488         int ret = 0;
489         int nr = _IOC_NR(cmd);
490
491         /*
492          * We only accept mixer (type 'M') ioctls.
493          */
494         FN_IN;
495         if (_IOC_TYPE(cmd) != 'M')
496                 return -EINVAL;
497
498         DPRINTK(" 0x%08x\n", cmd);
499
500         if (cmd == SOUND_MIXER_INFO) {
501                 struct mixer_info mi;
502
503                 strncpy(mi.id, "TSC2101", sizeof(mi.id));
504                 strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
505                 mi.modify_counter = tsc2101_local.mod_cnt;
506                 FN_OUT(1);
507                 return copy_to_user((void __user *)arg, &mi, sizeof(mi));
508         }
509
510         if (_IOC_DIR(cmd) & _IOC_WRITE) {
511                 ret = get_user(val, (int __user *)arg);
512                 if (ret)
513                         goto out;
514
515                 /* Ignore separate left/right channel for now,
516                  * even the codec does support it.
517                  */
518                 gain = val & 255;
519
520                 switch (nr) {
521                 case SOUND_MIXER_VOLUME:
522                         tsc2101_local.volume = val;
523                         tsc2101_local.mod_cnt++;
524                         ret = tsc2101_update(SET_VOLUME, gain);
525                         break;
526
527                 case SOUND_MIXER_LINE:
528                         tsc2101_local.line = val;
529                         tsc2101_local.mod_cnt++;
530                         ret = tsc2101_update(SET_LINE, gain);
531                         break;
532
533                 case SOUND_MIXER_MIC:
534                         tsc2101_local.mic = val;
535                         tsc2101_local.mod_cnt++;
536                         ret = tsc2101_update(SET_MIC, gain);
537                         break;
538
539                 case SOUND_MIXER_RECSRC:
540                         if ((val & SOUND_MASK_LINE) ||
541                             (val & SOUND_MASK_MIC)) {
542                                 if (tsc2101_local.recsrc != val) {
543                                         tsc2101_local.mod_cnt++;
544                                         tsc2101_update(SET_RECSRC, val);
545                                 }
546                         }
547                         else {
548                                 ret = -EINVAL;
549                         }
550                         break;
551
552                 default:
553                         ret = -EINVAL;
554                 }
555         }
556
557         if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
558                 ret = 0;
559
560                 switch (nr) {
561                 case SOUND_MIXER_VOLUME:
562                         val = tsc2101_local.volume;
563                         val = (tsc2101_local.volume << 8) |
564           tsc2101_local.volume;
565                         break;
566                 case SOUND_MIXER_LINE:
567                         val = (tsc2101_local.line << 8) |
568           tsc2101_local.line;
569                         break;
570                 case SOUND_MIXER_MIC:
571                         val = (tsc2101_local.mic << 8) |
572           tsc2101_local.mic;
573                         break;
574                 case SOUND_MIXER_RECSRC:
575                         val = tsc2101_local.recsrc;
576                         break;
577                 case SOUND_MIXER_RECMASK:
578                         val = REC_MASK;
579                         break;
580                 case SOUND_MIXER_DEVMASK:
581                         val = DEV_MASK;
582                         break;
583                 case SOUND_MIXER_CAPS:
584                         val = 0;
585                         break;
586                 case SOUND_MIXER_STEREODEVS:
587                         val = SOUND_MASK_VOLUME;
588                         break;
589                 default:
590                         val = 0;
591                         printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
592          "read ioctl flag specified\n");
593                         ret = -EINVAL;
594                         break;
595                 }
596
597                 if (ret == 0)
598                         ret = put_user(val, (int __user *)arg);
599         }
600       out:
601         FN_OUT(0);
602         return ret;
603
604 }
605
606 /*********************************************************************************
607  *
608  * omap_set_samplerate()
609  *
610  ********************************************************************************/
611 static int omap_set_samplerate(long sample_rate)
612 {
613         u8 count = 0;
614         u16 data = 0;
615         int clkgdv = 0;
616         /* wait for any frame to complete */
617         udelay(125);
618
619         /* Search for the right sample rate */
620         while ((reg_info[count].sample_rate != sample_rate) &&
621                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
622                 count++;
623         }
624         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
625                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
626                        (int)sample_rate);
627                 return -EPERM;
628         }
629
630         /* Set AC1 */
631         data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
632         /*Clear prev settings */
633         data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
634         data |=
635             AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
636                                                            divisor);
637         audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
638
639         /* Set the AC3 */
640         data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
641         /*Clear prev settings */
642         data &= ~(AC3_REFFS | AC3_SLVMS);
643         data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
644 #ifdef TSC_MASTER
645         data |= AC3_SLVMS;
646 #endif                          /* #ifdef TSC_MASTER */
647         audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
648
649         /* program the PLLs */
650         if (reg_info[count].fs_44kHz) {
651                 /* 44.1 khz - 12 MHz Mclk */
652                 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));    /* PVAL 1; I_VAL 7 */
653                 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
654         } else {
655                 /* 48 khz - 12 Mhz Mclk */
656                 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));    /* PVAL 1; I_VAL 8 */
657                 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
658         }
659
660         audio_samplerate = sample_rate;
661
662         /* Set the sample rate */
663 #ifndef TSC_MASTER
664         clkgdv =
665             DEFAULT_MCBSP_CLOCK / (sample_rate *
666                                    (DEFAULT_BITPERSAMPLE * 2 - 1));
667         if (clkgdv)
668                 initial_config.srgr1 =
669                     (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
670         else
671                 return (1);
672
673         /* Stereo Mode */
674         initial_config.srgr2 =
675             (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
676 #else
677         initial_config.srgr1 =
678             (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
679         initial_config.srgr2 =
680             ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
681
682 #endif                          /* end of #ifdef TSC_MASTER */
683         omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
684
685         return 0;
686 }
687
688 /*********************************************************************************
689  *
690  * omap_tsc2101_initialize() [hw_init() ]
691  *
692  ********************************************************************************/
693 static void omap_tsc2101_initialize(void *dummy)
694 {
695
696         DPRINTK("omap_tsc2101_initialize entry\n");
697
698         /* initialize with default sample rate */
699         audio_samplerate = AUDIO_RATE_DEFAULT;
700
701         omap_mcbsp_request(AUDIO_MCBSP);
702
703         /* if configured, then stop mcbsp */
704         omap_mcbsp_stop(AUDIO_MCBSP);
705
706         omap_tsc2101_enable();
707
708         omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
709         omap_mcbsp_start(AUDIO_MCBSP);
710         tsc2101_configure();
711
712 #ifdef TEST_KEYCLICK
713         tsc2101_testkeyclick();
714 #endif
715
716 #ifdef TONE_GEN
717         toneGen();
718 #endif
719
720         DPRINTK("omap_tsc2101_initialize exit\n");
721 }
722
723 /*********************************************************************************
724  *
725  * omap_tsc2101_shutdown() [hw_shutdown() ]
726  *
727  ********************************************************************************/
728 static void omap_tsc2101_shutdown(void *dummy)
729 {
730         /*
731            Turn off codec after it is done.
732            Can't do it immediately, since it may still have
733            buffered data.
734
735            Wait 20ms (arbitrary value) and then turn it off.
736          */
737
738         FN_IN;
739         set_current_state(TASK_INTERRUPTIBLE);
740         schedule_timeout(2);
741
742         omap_mcbsp_stop(AUDIO_MCBSP);
743         omap_mcbsp_free(AUDIO_MCBSP);
744
745         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
746                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
747
748         omap_tsc2101_disable();
749
750         FN_OUT(0);
751 }
752
753 /*********************************************************************************
754  *
755  * tsc2101_configure
756  *
757  ********************************************************************************/
758 static void tsc2101_configure(void)
759 {
760         FN_IN;
761
762         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
763
764         /*Mute Analog Sidetone */
765         /*Select MIC_INHED input for headset */
766         /*Cell Phone In not connected */
767         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
768                             MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
769
770         /* Set record source */
771         tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
772
773         /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
774         /* 1dB AGC hysteresis */
775         /* MICes bias 2V */
776         audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
777
778         /* Set codec output volume */
779         audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
780
781         /* DAC left and right routed to SPK2 */
782         /* SPK1/2 unmuted */
783         audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
784                             AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
785                             AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
786                             AC5_HDSCPTC);
787
788         /* OUT8P/N muted, CPOUT muted */
789
790         audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
791                             AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
792                             AC6_VGNDSCPTC);
793
794         /* Headset/Hook switch detect disabled */
795         audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
796
797         /* Left line input volume control */
798         tsc2101_update(SET_LINE, tsc2101_local.line);
799
800         /* mic input volume control */
801         tsc2101_update(SET_MIC, tsc2101_local.mic);
802
803         /* Left/Right headphone channel volume control */
804         /* Zero-cross detect on */
805         tsc2101_update(SET_VOLUME, tsc2101_local.volume);
806
807         /* clock configuration */
808         omap_set_samplerate(audio_samplerate);
809
810 #ifdef TSC_DUMP_REGISTERS
811         tsc2101_dumpRegisters();
812 #endif
813
814         FN_OUT(0);
815 }
816
817 #ifdef PROC_SUPPORT
818 static void tsc2101_start(void)
819 {
820         FN_IN;
821
822         audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
823
824         /*Mute Analog Sidetone */
825         /*Select MIC_INHED input for headset */
826         /*Cell Phone In not connected */
827         audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
828                             MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
829
830         /* Set record source */
831         tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
832
833         /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
834         /* 1dB AGC hysteresis */
835         /* MICes bias 2V */
836         audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
837
838         /* Set codec output volume */
839         audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
840
841         /* DAC left and right routed to SPK2 */
842         /* SPK1/2 unmuted */
843         audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
844                             AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
845                             AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
846                             AC5_HDSCPTC);
847
848         /* OUT8P/N muted, CPOUT muted */
849
850         audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
851                             AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
852                             AC6_VGNDSCPTC);
853
854         /* Headset/Hook switch detect disabled */
855         audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
856
857         /* Left line input volume control */
858         tsc2101_update(SET_LINE, tsc2101_local.line);
859
860         /* mic input volume control */
861         tsc2101_update(SET_MIC, tsc2101_local.mic);
862
863         /* Left/Right headphone channel volume control */
864         /* Zero-cross detect on */
865         tsc2101_update(SET_VOLUME, tsc2101_local.volume);
866
867         FN_OUT(0);
868
869 }
870 #endif
871
872 /******************************************************************************************
873  *
874  * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
875  * routine handles some platform specific ioctl's
876  *
877  ******************************************************************************************/
878 static int
879 omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
880 {
881         long val;
882         int ret = 0;
883
884         DPRINTK(" 0x%08x\n", cmd);
885
886         /*
887          * These are platform dependent ioctls which are not handled by the
888          * generic omap-audio module.
889          */
890         switch (cmd) {
891         case SNDCTL_DSP_STEREO:
892                 ret = get_user(val, (int __user *)arg);
893                 if (ret)
894                         return ret;
895                 /* the AIC23 is stereo only */
896                 ret = (val == 0) ? -EINVAL : 1;
897                 FN_OUT(1);
898                 return put_user(ret, (int __user *)arg);
899
900         case SNDCTL_DSP_CHANNELS:
901         case SOUND_PCM_READ_CHANNELS:
902                 /* the AIC23 is stereo only */
903                 FN_OUT(2);
904                 return put_user(2, (long __user *)arg);
905
906         case SNDCTL_DSP_SPEED:
907                 ret = get_user(val, (long __user *)arg);
908                 if (ret)
909                         break;
910                 ret = omap_set_samplerate(val);
911                 if (ret)
912                         break;
913                 /* fall through */
914
915         case SOUND_PCM_READ_RATE:
916                 FN_OUT(3);
917                 return put_user(audio_samplerate, (long __user *)arg);
918
919         case SOUND_PCM_READ_BITS:
920         case SNDCTL_DSP_SETFMT:
921         case SNDCTL_DSP_GETFMTS:
922                 /* we can do 16-bit only */
923                 FN_OUT(4);
924                 return put_user(AFMT_S16_LE, (long __user *)arg);
925
926         default:
927                 /* Maybe this is meant for the mixer (As per OSS Docs) */
928                 FN_OUT(5);
929                 return mixer_ioctl(inode, file, cmd, arg);
930         }
931
932         FN_OUT(0);
933         return ret;
934 }
935
936 /*********************************************************************************
937  *
938  * module_probe for TSC2101
939  *
940  ********************************************************************************/
941 static int omap_tsc2101_probe(void)
942 {
943         FN_IN;
944
945         /* Get the fops from audio oss driver */
946         if (!(omap_audio_fops = audio_get_fops())) {
947                 printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
948                 audio_unregister_codec(&tsc2101_state);
949                 return -EPERM;
950         }
951
952         /* register devices */
953         audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
954         mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
955
956 #ifdef PROC_SUPPORT
957         create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
958                                NULL /* parent dir */ ,
959                                codec_start, NULL /* client data */ );
960
961         create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
962                                NULL /* parent dir */ ,
963                                codec_stop, NULL /* client data */ );
964 #endif
965
966         /* Announcement Time */
967         printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
968                " Audio support initialized\n");
969
970         FN_OUT(0);
971         return 0;
972 }
973
974 /*********************************************************************************
975  *
976  * Module Remove for TSC2101
977  *
978  ********************************************************************************/
979 static void omap_tsc2101_remove(void)
980 {
981         FN_IN;
982         /* Un-Register the codec with the audio driver */
983         unregister_sound_dsp(audio_dev_id);
984         unregister_sound_mixer(mixer_dev_id);
985
986 #ifdef PROC_SUPPORT
987         remove_proc_entry(PROC_START_FILE, NULL);
988         remove_proc_entry(PROC_STOP_FILE, NULL);
989 #endif
990         FN_OUT(0);
991
992 }
993
994 /*********************************************************************************
995  *
996  * Module Suspend for TSC2101
997  *
998  ********************************************************************************/
999 static int omap_tsc2101_suspend(void)
1000 {
1001
1002         FN_OUT(0);
1003         return 0;
1004 }
1005
1006 /*********************************************************************************
1007  *
1008  * Module Resume for TSC2101
1009  *
1010  ********************************************************************************/
1011 static int omap_tsc2101_resume(void)
1012 {
1013
1014         FN_OUT(0);
1015         return 0;
1016 }
1017
1018 /*********************************************************************************
1019  *
1020  * module_init for TSC2101
1021  *
1022  ********************************************************************************/
1023 static int __init audio_tsc2101_init(void)
1024 {
1025
1026         int err = 0;
1027         FN_IN;
1028
1029         if (machine_is_omap_osk() || machine_is_omap_innovator())
1030                 return -ENODEV;
1031
1032         mutex_init(&tsc2101_state.mutex);
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");