2 * linux/sound/oss/omap-audio-tsc2101.c
4 * Glue driver for TSC2101 for OMAP processors
6 * Copyright (C) 2004 Texas Instruments, Inc.
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.
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.
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
25 /***************************** INCLUDES ************************************/
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
31 #include <linux/delay.h>
33 #include <linux/errno.h>
34 #include <linux/sound.h>
35 #include <linux/soundcard.h>
36 #include <linux/mutex.h>
38 #include <asm/uaccess.h>
39 #include <mach/hardware.h>
45 #include <asm/mach-types.h>
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)
55 #error "Unsupported configuration"
58 #include <asm/hardware/tsc2101.h>
59 #include <../drivers/ssi/omap-tsc2101.h>
61 /***************************** MACROS ************************************/
66 #include <linux/proc_fs.h>
67 #define PROC_START_FILE "driver/tsc2101-audio-start"
68 #define PROC_STOP_FILE "driver/tsc2101-audio-stop"
71 #define CODEC_NAME "TSC2101"
73 #ifdef CONFIG_ARCH_OMAP16XX
74 #define PLATFORM_NAME "OMAP16XX"
75 #elif defined(CONFIG_ARCH_OMAP24XX)
76 #define PLATFORM_NAME "OMAP2"
79 /* Define to set the tsc as the master w.r.t McBSP */
83 * AUDIO related MACROS
85 #define DEFAULT_BITPERSAMPLE 16
86 #define AUDIO_RATE_DEFAULT 44100
87 #define PAGE2_AUDIO_CODEC_REGISTERS (2)
90 /* Select the McBSP For Audio */
91 /* 16XX is MCBSP1 and 24XX is MCBSP2*/
92 /* see include/asm-arm/arch-omap/mcbsp.h */
94 #error "UnSupported Configuration"
97 #define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
98 #define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME)
105 #define DEFAULT_VOLUME 93
106 #define DEFAULT_INPUT_VOLUME 20 /* An minimal volume */
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
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
122 /*********** Debug Macros ********/
123 /* To Generate a rather shrill tone -test the entire path */
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
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)
141 #define DPRINTK( x... )
146 /***************************** Data Structures **********************************/
148 static int audio_ifc_start(void)
150 omap_mcbsp_start(AUDIO_MCBSP);
154 static int audio_ifc_stop(void)
156 omap_mcbsp_stop(AUDIO_MCBSP);
160 static audio_stream_t output_stream = {
162 .dma_dev = AUDIO_DMA_TX,
163 .input_or_output = FMODE_WRITE,
164 .hw_start = audio_ifc_start,
165 .hw_stop = audio_ifc_stop,
168 static audio_stream_t input_stream = {
170 .dma_dev = AUDIO_DMA_RX,
171 .input_or_output = FMODE_READ,
172 .hw_start = audio_ifc_start,
173 .hw_stop = audio_ifc_stop,
176 static int audio_dev_id, mixer_dev_id;
184 } tsc2101_local_info;
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,
194 struct sample_rate_reg_info {
197 u8 fs_44kHz; /* if 0 48 khz, if 1 44.1 khz fsref */
200 /* To Store the default sample rate */
201 static long audio_samplerate = AUDIO_RATE_DEFAULT;
203 static const struct sample_rate_reg_info
204 reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
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),
241 .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
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)
249 .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
251 .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
252 #endif /* tsc Master defs */
254 #endif /* platform specific inits */
257 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
259 static void omap_tsc2101_initialize(void *dummy);
261 static void omap_tsc2101_shutdown(void *dummy);
263 static int omap_tsc2101_ioctl(struct inode *inode, struct file *file,
264 uint cmd, ulong arg);
266 static int omap_tsc2101_probe(void);
268 static void omap_tsc2101_remove(void);
270 static int omap_tsc2101_suspend(void);
272 static int omap_tsc2101_resume(void);
274 static void tsc2101_configure(void);
276 static int mixer_open(struct inode *inode, struct file *file);
278 static int mixer_release(struct inode *inode, struct file *file);
280 static int mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
284 void tsc2101_testkeyclick(void);
291 #ifdef TSC_DUMP_REGISTERS
292 static void tsc2101_dumpRegisters(void);
296 static int codec_start(char *buf, char **start, off_t offset, int count,
297 int *eof, void *data);
299 static int codec_stop(char *buf, char **start, off_t offset, int count,
300 int *eof, void *data);
302 static void tsc2101_start(void);
305 /******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
307 /* File Op structure for mixer */
308 static struct file_operations omap_mixer_fops = {
310 .release = mixer_release,
311 .ioctl = mixer_ioctl,
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 */
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,
330 /* This will be defined in the Audio.h */
331 static struct file_operations *omap_audio_fops;
333 /***************************** MODULES SPECIFIC FUNCTIONs *******************************/
335 /*********************************************************************************
337 * Simplified write for tsc Audio
339 *********************************************************************************/
340 static __inline__ void audio_tsc2101_write(u8 address, u16 data)
342 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
345 /*********************************************************************************
347 * Simplified read for tsc Audio
349 *********************************************************************************/
350 static __inline__ u16 audio_tsc2101_read(u8 address)
352 return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
355 /*********************************************************************************
360 ********************************************************************************/
361 static int tsc2101_update(int flag, int val)
369 if (val < 0 || val > 100) {
370 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
373 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
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);
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);
389 if (val < 0 || val > 100) {
390 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
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));
402 if (val < 0 || val > 100) {
403 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
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));
416 * If more than one recording device selected,
417 * disable the device that is currently in use.
419 if (hweight32(val) > 1)
420 val &= ~tsc2101_local.recsrc;
422 data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
423 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
425 if (val == SOUND_MASK_MIC) {
426 data |= MPC_MICSEL(1);
427 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
429 else if (val == SOUND_MASK_LINE) {
430 data |= MPC_MICSEL(0);
431 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
434 printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
435 " value specified\n");
438 tsc2101_local.recsrc = val;
441 printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
450 /*********************************************************************************
454 ********************************************************************************/
455 static int mixer_open(struct inode *inode, struct file *file)
457 /* Any mixer specific initialization */
459 /* Initalize the tsc2101 */
460 omap_tsc2101_enable();
465 /*********************************************************************************
469 ********************************************************************************/
470 static int mixer_release(struct inode *inode, struct file *file)
472 /* Any mixer specific Un-initialization */
473 omap_tsc2101_disable();
478 /*********************************************************************************
482 ********************************************************************************/
484 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
489 int nr = _IOC_NR(cmd);
492 * We only accept mixer (type 'M') ioctls.
495 if (_IOC_TYPE(cmd) != 'M')
498 DPRINTK(" 0x%08x\n", cmd);
500 if (cmd == SOUND_MIXER_INFO) {
501 struct mixer_info mi;
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;
507 return copy_to_user((void __user *)arg, &mi, sizeof(mi));
510 if (_IOC_DIR(cmd) & _IOC_WRITE) {
511 ret = get_user(val, (int __user *)arg);
515 /* Ignore separate left/right channel for now,
516 * even the codec does support it.
521 case SOUND_MIXER_VOLUME:
522 tsc2101_local.volume = val;
523 tsc2101_local.mod_cnt++;
524 ret = tsc2101_update(SET_VOLUME, gain);
527 case SOUND_MIXER_LINE:
528 tsc2101_local.line = val;
529 tsc2101_local.mod_cnt++;
530 ret = tsc2101_update(SET_LINE, gain);
533 case SOUND_MIXER_MIC:
534 tsc2101_local.mic = val;
535 tsc2101_local.mod_cnt++;
536 ret = tsc2101_update(SET_MIC, gain);
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);
557 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
561 case SOUND_MIXER_VOLUME:
562 val = tsc2101_local.volume;
563 val = (tsc2101_local.volume << 8) |
564 tsc2101_local.volume;
566 case SOUND_MIXER_LINE:
567 val = (tsc2101_local.line << 8) |
570 case SOUND_MIXER_MIC:
571 val = (tsc2101_local.mic << 8) |
574 case SOUND_MIXER_RECSRC:
575 val = tsc2101_local.recsrc;
577 case SOUND_MIXER_RECMASK:
580 case SOUND_MIXER_DEVMASK:
583 case SOUND_MIXER_CAPS:
586 case SOUND_MIXER_STEREODEVS:
587 val = SOUND_MASK_VOLUME;
591 printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
592 "read ioctl flag specified\n");
598 ret = put_user(val, (int __user *)arg);
606 /*********************************************************************************
608 * omap_set_samplerate()
610 ********************************************************************************/
611 static int omap_set_samplerate(long sample_rate)
616 /* wait for any frame to complete */
619 /* Search for the right sample rate */
620 while ((reg_info[count].sample_rate != sample_rate) &&
621 (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
624 if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
625 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
631 data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
632 /*Clear prev settings */
633 data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
635 AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
637 audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
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;
646 #endif /* #ifdef TSC_MASTER */
647 audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
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 */
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 */
660 audio_samplerate = sample_rate;
662 /* Set the sample rate */
665 DEFAULT_MCBSP_CLOCK / (sample_rate *
666 (DEFAULT_BITPERSAMPLE * 2 - 1));
668 initial_config.srgr1 =
669 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
674 initial_config.srgr2 =
675 (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
677 initial_config.srgr1 =
678 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
679 initial_config.srgr2 =
680 ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
682 #endif /* end of #ifdef TSC_MASTER */
683 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
688 /*********************************************************************************
690 * omap_tsc2101_initialize() [hw_init() ]
692 ********************************************************************************/
693 static void omap_tsc2101_initialize(void *dummy)
696 DPRINTK("omap_tsc2101_initialize entry\n");
698 /* initialize with default sample rate */
699 audio_samplerate = AUDIO_RATE_DEFAULT;
701 omap_mcbsp_request(AUDIO_MCBSP);
703 /* if configured, then stop mcbsp */
704 omap_mcbsp_stop(AUDIO_MCBSP);
706 omap_tsc2101_enable();
708 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
709 omap_mcbsp_start(AUDIO_MCBSP);
713 tsc2101_testkeyclick();
720 DPRINTK("omap_tsc2101_initialize exit\n");
723 /*********************************************************************************
725 * omap_tsc2101_shutdown() [hw_shutdown() ]
727 ********************************************************************************/
728 static void omap_tsc2101_shutdown(void *dummy)
731 Turn off codec after it is done.
732 Can't do it immediately, since it may still have
735 Wait 20ms (arbitrary value) and then turn it off.
739 set_current_state(TASK_INTERRUPTIBLE);
742 omap_mcbsp_stop(AUDIO_MCBSP);
743 omap_mcbsp_free(AUDIO_MCBSP);
745 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
746 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
748 omap_tsc2101_disable();
753 /*********************************************************************************
757 ********************************************************************************/
758 static void tsc2101_configure(void)
762 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
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);
770 /* Set record source */
771 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
773 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
774 /* 1dB AGC hysteresis */
776 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
778 /* Set codec output volume */
779 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
781 /* DAC left and right routed to SPK2 */
783 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
784 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
785 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
788 /* OUT8P/N muted, CPOUT muted */
790 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
791 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
794 /* Headset/Hook switch detect disabled */
795 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
797 /* Left line input volume control */
798 tsc2101_update(SET_LINE, tsc2101_local.line);
800 /* mic input volume control */
801 tsc2101_update(SET_MIC, tsc2101_local.mic);
803 /* Left/Right headphone channel volume control */
804 /* Zero-cross detect on */
805 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
807 /* clock configuration */
808 omap_set_samplerate(audio_samplerate);
810 #ifdef TSC_DUMP_REGISTERS
811 tsc2101_dumpRegisters();
818 static void tsc2101_start(void)
822 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
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);
830 /* Set record source */
831 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
833 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
834 /* 1dB AGC hysteresis */
836 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
838 /* Set codec output volume */
839 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
841 /* DAC left and right routed to SPK2 */
843 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
844 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
845 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
848 /* OUT8P/N muted, CPOUT muted */
850 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
851 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
854 /* Headset/Hook switch detect disabled */
855 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
857 /* Left line input volume control */
858 tsc2101_update(SET_LINE, tsc2101_local.line);
860 /* mic input volume control */
861 tsc2101_update(SET_MIC, tsc2101_local.mic);
863 /* Left/Right headphone channel volume control */
864 /* Zero-cross detect on */
865 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
872 /******************************************************************************************
874 * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
875 * routine handles some platform specific ioctl's
877 ******************************************************************************************/
879 omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
884 DPRINTK(" 0x%08x\n", cmd);
887 * These are platform dependent ioctls which are not handled by the
888 * generic omap-audio module.
891 case SNDCTL_DSP_STEREO:
892 ret = get_user(val, (int __user *)arg);
895 /* the AIC23 is stereo only */
896 ret = (val == 0) ? -EINVAL : 1;
898 return put_user(ret, (int __user *)arg);
900 case SNDCTL_DSP_CHANNELS:
901 case SOUND_PCM_READ_CHANNELS:
902 /* the AIC23 is stereo only */
904 return put_user(2, (long __user *)arg);
906 case SNDCTL_DSP_SPEED:
907 ret = get_user(val, (long __user *)arg);
910 ret = omap_set_samplerate(val);
915 case SOUND_PCM_READ_RATE:
917 return put_user(audio_samplerate, (long __user *)arg);
919 case SOUND_PCM_READ_BITS:
920 case SNDCTL_DSP_SETFMT:
921 case SNDCTL_DSP_GETFMTS:
922 /* we can do 16-bit only */
924 return put_user(AFMT_S16_LE, (long __user *)arg);
927 /* Maybe this is meant for the mixer (As per OSS Docs) */
929 return mixer_ioctl(inode, file, cmd, arg);
936 /*********************************************************************************
938 * module_probe for TSC2101
940 ********************************************************************************/
941 static int omap_tsc2101_probe(void)
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);
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);
957 create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
958 NULL /* parent dir */ ,
959 codec_start, NULL /* client data */ );
961 create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
962 NULL /* parent dir */ ,
963 codec_stop, NULL /* client data */ );
966 /* Announcement Time */
967 printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
968 " Audio support initialized\n");
974 /*********************************************************************************
976 * Module Remove for TSC2101
978 ********************************************************************************/
979 static void omap_tsc2101_remove(void)
982 /* Un-Register the codec with the audio driver */
983 unregister_sound_dsp(audio_dev_id);
984 unregister_sound_mixer(mixer_dev_id);
987 remove_proc_entry(PROC_START_FILE, NULL);
988 remove_proc_entry(PROC_STOP_FILE, NULL);
994 /*********************************************************************************
996 * Module Suspend for TSC2101
998 ********************************************************************************/
999 static int omap_tsc2101_suspend(void)
1006 /*********************************************************************************
1008 * Module Resume for TSC2101
1010 ********************************************************************************/
1011 static int omap_tsc2101_resume(void)
1018 /*********************************************************************************
1020 * module_init for TSC2101
1022 ********************************************************************************/
1023 static int __init audio_tsc2101_init(void)
1029 if (machine_is_omap_osk() || machine_is_omap_innovator())
1032 mutex_init(&tsc2101_state.mutex);
1034 /* register the codec with the audio driver */
1035 if ((err = audio_register_codec(&tsc2101_state))) {
1037 "Failed to register TSC driver with Audio OSS Driver\n");
1043 /*********************************************************************************
1045 * module_exit for TSC2101
1047 ********************************************************************************/
1048 static void __exit audio_tsc2101_exit(void)
1052 (void)audio_unregister_codec(&tsc2101_state);
1057 /**************************** DEBUG FUNCTIONS ***********************************/
1059 /*********************************************************************************
1061 * This is a test to generate various keyclick sound on tsc.
1062 * verifies if the tsc and the spi interfaces are operational.
1064 ********************************************************************************/
1065 #ifdef TEST_KEYCLICK
1066 void tsc2101_testkeyclick(void)
1069 u16 old_reg_val, reg_val;
1073 old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
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);
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) {
1093 if (uTryVal > 2000) {
1095 "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
1098 "uTryVal == %d: Read back new reg val= 0x%x\n",
1101 (TSC2101_AUDIO_CTRL_2));
1103 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
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");
1112 } /* End of tsc2101_testkeyclick */
1114 #endif /* TEST_KEYCLICK */
1116 /*********************************************************************************
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)
1121 ********************************************************************************/
1123 /* Generates a shrill 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
1164 printk(KERN_INFO "TONE GEN TEST :");
1166 for (count = 0; count < 5000; count++) {
1168 for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
1169 ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
1173 } else if (ret == -2) {
1174 printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
1179 printk(KERN_INFO "SUCCESS\n");
1182 #endif /* End of TONE_GEN */
1184 /*********************************************************************************
1186 * TSC_DUMP_REGISTERS:
1187 * This will dump the entire register set of Page 2 tsc2101.
1188 * Useful for major goof ups
1190 ********************************************************************************/
1191 #ifdef TSC_DUMP_REGISTERS
1192 static void tsc2101_dumpRegisters(void)
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);
1203 #endif /* End of #ifdef TSC_DUMP_REGISTERS */
1206 static int codec_start(char *buf, char **start, off_t offset, int count,
1207 int *eof, void *data)
1209 omap_tsc2101_enable();
1211 printk("Codec initialization done.\n");
1214 static int codec_stop(char *buf, char **start, off_t offset, int count,
1215 int *eof, void *data)
1218 omap_tsc2101_disable();
1219 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
1220 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
1221 printk("Codec shutdown.\n");
1226 /*********************************************************************************
1228 * Other misc management, registration etc
1230 ********************************************************************************/
1231 module_init(audio_tsc2101_init);
1232 module_exit(audio_tsc2101_exit);
1234 MODULE_AUTHOR("Texas Instruments");
1236 ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
1237 MODULE_LICENSE("GPL");