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 <asm/hardware.h>
40 #include <asm/arch/dma.h>
42 #include <asm/hardware.h>
44 #include <asm/arch/mux.h>
45 #include <asm/arch/io.h>
46 #include <asm/mach-types.h>
48 #include "omap-audio.h"
49 #include "omap-audio-dma-intfc.h"
50 #include <asm/arch/mcbsp.h>
51 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
52 #include <../drivers/ssi/omap-uwire.h>
53 #include <asm/arch/dsp_common.h>
54 #elif defined(CONFIG_ARCH_OMAP24XX)
56 #error "Unsupported configuration"
59 #include <asm/hardware/tsc2101.h>
60 #include <../drivers/ssi/omap-tsc2101.h>
62 /***************************** MACROS ************************************/
67 #include <linux/proc_fs.h>
68 #define PROC_START_FILE "driver/tsc2101-audio-start"
69 #define PROC_STOP_FILE "driver/tsc2101-audio-stop"
72 #define CODEC_NAME "TSC2101"
74 #ifdef CONFIG_ARCH_OMAP16XX
75 #define PLATFORM_NAME "OMAP16XX"
76 #elif CONFIG_MACH_OMAP_H6300
77 #define PLATFORM_NAME "OMAP15XX"
78 #elif defined(CONFIG_ARCH_OMAP24XX)
79 #define PLATFORM_NAME "OMAP2"
82 #if CONFIG_ARCH_OMAP16XX
83 #define OMAP_DSP_BASE 0xE0000000
86 /* Define to set the tsc as the master w.r.t McBSP */
90 * AUDIO related MACROS
92 #define DEFAULT_BITPERSAMPLE 16
93 #define AUDIO_RATE_DEFAULT 44100
94 #define PAGE2_AUDIO_CODEC_REGISTERS (2)
97 /* Select the McBSP For Audio */
98 /* 16XX is MCBSP1 and 24XX is MCBSP2*/
99 /* see include/asm-arm/arch-omap/mcbsp.h */
101 #error "UnSupported Configuration"
104 #define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
105 #define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME)
112 #define DEFAULT_VOLUME 93
113 #define DEFAULT_INPUT_VOLUME 20 /* An minimal volume */
115 /* Tsc Audio Specific */
116 #define NUMBER_SAMPLE_RATES_SUPPORTED 16
117 #define OUTPUT_VOLUME_MIN 0x7F
118 #define OUTPUT_VOLUME_MAX 0x32
119 #define OUTPUT_VOLUME_RANGE (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
120 #define OUTPUT_VOLUME_MASK OUTPUT_VOLUME_MIN
121 #define DEFAULT_VOLUME_LEVEL OUTPUT_VOLUME_MAX
123 /* use input vol of 75 for 0dB gain */
124 #define INPUT_VOLUME_MIN 0x0
125 #define INPUT_VOLUME_MAX 0x7D
126 #define INPUT_VOLUME_RANGE (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
127 #define INPUT_VOLUME_MASK INPUT_VOLUME_MAX
129 /*********** Debug Macros ********/
130 /* To Generate a rather shrill tone -test the entire path */
132 ///* To Generate a tone for each keyclick - test the tsc,spi paths*/
133 //#define TEST_KEYCLICK
134 /* To dump the tsc registers for debug */
135 //#define TSC_DUMP_REGISTERS
144 #define DPRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
145 #define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
146 #define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
148 #define DPRINTK( x... )
153 /***************************** Data Structures **********************************/
155 static int audio_ifc_start(void)
157 omap_mcbsp_start(AUDIO_MCBSP);
161 static int audio_ifc_stop(void)
163 omap_mcbsp_stop(AUDIO_MCBSP);
167 static audio_stream_t output_stream = {
169 .dma_dev = AUDIO_DMA_TX,
170 .input_or_output = FMODE_WRITE,
171 .hw_start = audio_ifc_start,
172 .hw_stop = audio_ifc_stop,
175 static audio_stream_t input_stream = {
177 .dma_dev = AUDIO_DMA_RX,
178 .input_or_output = FMODE_READ,
179 .hw_start = audio_ifc_start,
180 .hw_stop = audio_ifc_stop,
183 static int audio_dev_id, mixer_dev_id;
191 } tsc2101_local_info;
193 static tsc2101_local_info tsc2101_local = {
194 volume: DEFAULT_VOLUME,
195 line: DEFAULT_INPUT_VOLUME,
196 mic: DEFAULT_INPUT_VOLUME,
197 recsrc: SOUND_MASK_LINE,
201 struct sample_rate_reg_info {
204 u8 fs_44kHz; /* if 0 48 khz, if 1 44.1 khz fsref */
207 /* To Store the default sample rate */
208 static long audio_samplerate = AUDIO_RATE_DEFAULT;
210 static const struct sample_rate_reg_info
211 reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
238 static struct omap_mcbsp_reg_cfg initial_config = {
239 #ifdef CONFIG_MACH_OMAP_H6300
250 .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
251 .spcr1 = RINTM(3) | RRST,
252 .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
253 RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
254 .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
255 .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
256 XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
257 .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
259 .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
261 /* platform specific initialization */
262 #ifdef CONFIG_MACH_OMAP_H2
263 .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
264 #elif defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H4) || defined(CONFIG_MACH_OMAP_APOLLON)
267 .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
269 .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
270 #endif /* tsc Master defs */
272 #endif /* platform specific inits */
273 #endif /* CONFIG_MACH_OMAP_H6300 */
276 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
278 static void omap_tsc2101_initialize(void *dummy);
280 static void omap_tsc2101_shutdown(void *dummy);
282 static int omap_tsc2101_ioctl(struct inode *inode, struct file *file,
283 uint cmd, ulong arg);
285 static int omap_tsc2101_probe(void);
287 static void omap_tsc2101_remove(void);
289 static int omap_tsc2101_suspend(void);
291 static int omap_tsc2101_resume(void);
293 static void tsc2101_configure(void);
295 static int mixer_open(struct inode *inode, struct file *file);
297 static int mixer_release(struct inode *inode, struct file *file);
299 static int mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
303 void tsc2101_testkeyclick(void);
310 #ifdef TSC_DUMP_REGISTERS
311 static void tsc2101_dumpRegisters(void);
315 static int codec_start(char *buf, char **start, off_t offset, int count,
316 int *eof, void *data);
318 static int codec_stop(char *buf, char **start, off_t offset, int count,
319 int *eof, void *data);
321 static void tsc2101_start(void);
324 /******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
326 /* File Op structure for mixer */
327 static struct file_operations omap_mixer_fops = {
329 .release = mixer_release,
330 .ioctl = mixer_ioctl,
334 /* To store characteristic info regarding the codec for the audio driver */
335 static audio_state_t tsc2101_state = {
336 .output_stream = &output_stream,
337 .input_stream = &input_stream,
338 /* .need_tx_for_rx = 1, //Once the Full Duplex works */
340 .hw_init = omap_tsc2101_initialize,
341 .hw_shutdown = omap_tsc2101_shutdown,
342 .client_ioctl = omap_tsc2101_ioctl,
343 .hw_probe = omap_tsc2101_probe,
344 .hw_remove = omap_tsc2101_remove,
345 .hw_suspend = omap_tsc2101_suspend,
346 .hw_resume = omap_tsc2101_resume,
347 .mutex = __MUTEX_INITIALIZER(tsc2101_state.mutex),
350 /* This will be defined in the Audio.h */
351 static struct file_operations *omap_audio_fops;
353 /***************************** MODULES SPECIFIC FUNCTIONs *******************************/
355 /*********************************************************************************
357 * Simplified write for tsc Audio
359 *********************************************************************************/
360 static __inline__ void audio_tsc2101_write(u8 address, u16 data)
362 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
365 /*********************************************************************************
367 * Simplified read for tsc Audio
369 *********************************************************************************/
370 static __inline__ u16 audio_tsc2101_read(u8 address)
372 return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
375 /*********************************************************************************
380 ********************************************************************************/
381 static int tsc2101_update(int flag, int val)
389 if (val < 0 || val > 100) {
390 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
393 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
395 ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
396 /* invert the value for getting the proper range 0 min and 100 max */
397 volume = OUTPUT_VOLUME_MIN - volume;
398 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
400 ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
401 DGC_DARVL(OUTPUT_VOLUME_MIN));
402 data |= DGC_DALVL(volume) | DGC_DARVL(volume);
403 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
404 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
409 if (val < 0 || val > 100) {
410 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
413 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
414 /* NOTE: 0 is minimum volume and not mute */
415 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
416 /* Handset Input not muted, AGC for Handset In off */
417 audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
418 HGC_ADPGA_HED(volume));
422 if (val < 0 || val > 100) {
423 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
426 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
427 /* NOTE: 0 is minimum volume and not mute */
428 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
429 /* Handset Input not muted, AGC for Handset In off */
430 audio_tsc2101_write(TSC2101_HANDSET_GAIN_CTRL,
431 HNGC_ADPGA_HND(volume));
436 * If more than one recording device selected,
437 * disable the device that is currently in use.
439 if (hweight32(val) > 1)
440 val &= ~tsc2101_local.recsrc;
442 data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
443 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
445 if (val == SOUND_MASK_MIC) {
446 data |= MPC_MICSEL(1);
447 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
449 else if (val == SOUND_MASK_LINE) {
450 data |= MPC_MICSEL(0);
451 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
454 printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
455 " value specified\n");
458 tsc2101_local.recsrc = val;
461 printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
470 /*********************************************************************************
474 ********************************************************************************/
475 static int mixer_open(struct inode *inode, struct file *file)
477 /* Any mixer specific initialization */
479 /* Initalize the tsc2101 */
480 omap_tsc2101_enable();
485 /*********************************************************************************
489 ********************************************************************************/
490 static int mixer_release(struct inode *inode, struct file *file)
492 /* Any mixer specific Un-initialization */
493 omap_tsc2101_disable();
498 /*********************************************************************************
502 ********************************************************************************/
504 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
509 int nr = _IOC_NR(cmd);
512 * We only accept mixer (type 'M') ioctls.
515 if (_IOC_TYPE(cmd) != 'M')
518 DPRINTK(" 0x%08x\n", cmd);
520 if (cmd == SOUND_MIXER_INFO) {
521 struct mixer_info mi;
523 strncpy(mi.id, "TSC2101", sizeof(mi.id));
524 strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
525 mi.modify_counter = tsc2101_local.mod_cnt;
527 return copy_to_user((void __user *)arg, &mi, sizeof(mi));
530 if (_IOC_DIR(cmd) & _IOC_WRITE) {
531 ret = get_user(val, (int __user *)arg);
535 /* Ignore separate left/right channel for now,
536 * even the codec does support it.
541 case SOUND_MIXER_VOLUME:
542 tsc2101_local.volume = val;
543 tsc2101_local.mod_cnt++;
544 ret = tsc2101_update(SET_VOLUME, gain);
547 case SOUND_MIXER_LINE:
548 tsc2101_local.line = val;
549 tsc2101_local.mod_cnt++;
550 ret = tsc2101_update(SET_LINE, gain);
553 case SOUND_MIXER_MIC:
554 tsc2101_local.mic = val;
555 tsc2101_local.mod_cnt++;
556 ret = tsc2101_update(SET_MIC, gain);
559 case SOUND_MIXER_RECSRC:
560 if ((val & SOUND_MASK_LINE) ||
561 (val & SOUND_MASK_MIC)) {
562 if (tsc2101_local.recsrc != val) {
563 tsc2101_local.mod_cnt++;
564 tsc2101_update(SET_RECSRC, val);
577 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
581 case SOUND_MIXER_VOLUME:
582 val = tsc2101_local.volume;
583 val = (tsc2101_local.volume << 8) |
584 tsc2101_local.volume;
586 case SOUND_MIXER_LINE:
587 val = (tsc2101_local.line << 8) |
590 case SOUND_MIXER_MIC:
591 val = (tsc2101_local.mic << 8) |
594 case SOUND_MIXER_RECSRC:
595 val = tsc2101_local.recsrc;
597 case SOUND_MIXER_RECMASK:
600 case SOUND_MIXER_DEVMASK:
603 case SOUND_MIXER_CAPS:
606 case SOUND_MIXER_STEREODEVS:
607 val = SOUND_MASK_VOLUME;
611 printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
612 "read ioctl flag specified\n");
618 ret = put_user(val, (int __user *)arg);
626 /*********************************************************************************
628 * omap_set_samplerate()
630 ********************************************************************************/
631 static int omap_set_samplerate(long sample_rate)
636 /* wait for any frame to complete */
639 /* Search for the right sample rate */
640 while ((reg_info[count].sample_rate != sample_rate) &&
641 (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
644 if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
645 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
651 data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
652 /*Clear prev settings */
653 data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
655 AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
657 audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
660 data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
661 /*Clear prev settings */
662 data &= ~(AC3_REFFS | AC3_SLVMS);
663 data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
666 #endif /* #ifdef TSC_MASTER */
667 audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
669 /* program the PLLs */
670 if (reg_info[count].fs_44kHz) {
671 /* 44.1 khz - 12 MHz Mclk */
672 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */
673 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */
675 /* 48 khz - 12 Mhz Mclk */
676 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */
677 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */
680 audio_samplerate = sample_rate;
682 /* Set the sample rate */
685 DEFAULT_MCBSP_CLOCK / (sample_rate *
686 (DEFAULT_BITPERSAMPLE * 2 - 1));
688 initial_config.srgr1 =
689 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
694 initial_config.srgr2 =
695 (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
697 initial_config.srgr1 =
698 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
699 initial_config.srgr2 =
700 ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
702 #endif /* end of #ifdef TSC_MASTER */
703 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
708 /*********************************************************************************
710 * omap_tsc2101_initialize() [hw_init() ]
712 ********************************************************************************/
713 static void omap_tsc2101_initialize(void *dummy)
716 DPRINTK("omap_tsc2101_initialize entry\n");
718 /* initialize with default sample rate */
719 audio_samplerate = AUDIO_RATE_DEFAULT;
721 omap_mcbsp_request(AUDIO_MCBSP);
723 /* if configured, then stop mcbsp */
724 omap_mcbsp_stop(AUDIO_MCBSP);
726 omap_tsc2101_enable();
728 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
729 omap_mcbsp_start(AUDIO_MCBSP);
733 tsc2101_testkeyclick();
740 DPRINTK("omap_tsc2101_initialize exit\n");
743 /*********************************************************************************
745 * omap_tsc2101_shutdown() [hw_shutdown() ]
747 ********************************************************************************/
748 static void omap_tsc2101_shutdown(void *dummy)
751 Turn off codec after it is done.
752 Can't do it immediately, since it may still have
755 Wait 20ms (arbitrary value) and then turn it off.
759 set_current_state(TASK_INTERRUPTIBLE);
762 omap_mcbsp_stop(AUDIO_MCBSP);
763 omap_mcbsp_free(AUDIO_MCBSP);
765 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
766 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
768 omap_tsc2101_disable();
773 /*********************************************************************************
777 ********************************************************************************/
778 static void tsc2101_configure(void)
782 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
784 /*Mute Analog Sidetone */
785 /*Select MIC_INHED input for headset */
786 /*Cell Phone In not connected */
787 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
788 MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
790 /* Set record source */
791 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
793 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
794 /* 1dB AGC hysteresis */
796 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
798 /* Set codec output volume */
799 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
801 /* DAC left and right routed to SPK2 */
803 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
804 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
805 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
808 /* OUT8P/N muted, CPOUT muted */
810 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
811 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
814 /* Headset/Hook switch detect disabled */
815 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
817 /* Left line input volume control */
818 tsc2101_update(SET_LINE, tsc2101_local.line);
820 /* mic input volume control */
821 tsc2101_update(SET_MIC, tsc2101_local.mic);
823 /* Left/Right headphone channel volume control */
824 /* Zero-cross detect on */
825 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
827 /* clock configuration */
828 omap_set_samplerate(audio_samplerate);
830 #ifdef TSC_DUMP_REGISTERS
831 tsc2101_dumpRegisters();
838 static void tsc2101_start(void)
842 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
844 /*Mute Analog Sidetone */
845 /*Select MIC_INHED input for headset */
846 /*Cell Phone In not connected */
847 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
848 MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
850 /* Set record source */
851 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
853 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
854 /* 1dB AGC hysteresis */
856 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
858 /* Set codec output volume */
859 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
861 /* DAC left and right routed to SPK2 */
863 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
864 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
865 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
868 /* OUT8P/N muted, CPOUT muted */
870 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
871 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
874 /* Headset/Hook switch detect disabled */
875 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
877 /* Left line input volume control */
878 tsc2101_update(SET_LINE, tsc2101_local.line);
880 /* mic input volume control */
881 tsc2101_update(SET_MIC, tsc2101_local.mic);
883 /* Left/Right headphone channel volume control */
884 /* Zero-cross detect on */
885 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
892 /******************************************************************************************
894 * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
895 * routine handles some platform specific ioctl's
897 ******************************************************************************************/
899 omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
904 DPRINTK(" 0x%08x\n", cmd);
907 * These are platform dependent ioctls which are not handled by the
908 * generic omap-audio module.
911 case SNDCTL_DSP_STEREO:
912 ret = get_user(val, (int __user *)arg);
915 /* the AIC23 is stereo only */
916 ret = (val == 0) ? -EINVAL : 1;
918 return put_user(ret, (int __user *)arg);
920 case SNDCTL_DSP_CHANNELS:
921 case SOUND_PCM_READ_CHANNELS:
922 /* the AIC23 is stereo only */
924 return put_user(2, (long __user *)arg);
926 case SNDCTL_DSP_SPEED:
927 ret = get_user(val, (long __user *)arg);
930 ret = omap_set_samplerate(val);
935 case SOUND_PCM_READ_RATE:
937 return put_user(audio_samplerate, (long __user *)arg);
939 case SOUND_PCM_READ_BITS:
940 case SNDCTL_DSP_SETFMT:
941 case SNDCTL_DSP_GETFMTS:
942 /* we can do 16-bit only */
944 return put_user(AFMT_S16_LE, (long __user *)arg);
947 /* Maybe this is meant for the mixer (As per OSS Docs) */
949 return mixer_ioctl(inode, file, cmd, arg);
956 /*********************************************************************************
958 * module_probe for TSC2101
960 ********************************************************************************/
961 static int omap_tsc2101_probe(void)
965 /* Get the fops from audio oss driver */
966 if (!(omap_audio_fops = audio_get_fops())) {
967 printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
968 audio_unregister_codec(&tsc2101_state);
972 /* register devices */
973 audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
974 mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
977 create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
978 NULL /* parent dir */ ,
979 codec_start, NULL /* client data */ );
981 create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
982 NULL /* parent dir */ ,
983 codec_stop, NULL /* client data */ );
986 /* Announcement Time */
987 printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
988 " Audio support initialized\n");
994 /*********************************************************************************
996 * Module Remove for TSC2101
998 ********************************************************************************/
999 static void omap_tsc2101_remove(void)
1002 /* Un-Register the codec with the audio driver */
1003 unregister_sound_dsp(audio_dev_id);
1004 unregister_sound_mixer(mixer_dev_id);
1007 remove_proc_entry(PROC_START_FILE, NULL);
1008 remove_proc_entry(PROC_STOP_FILE, NULL);
1014 /*********************************************************************************
1016 * Module Suspend for TSC2101
1018 ********************************************************************************/
1019 static int omap_tsc2101_suspend(void)
1026 /*********************************************************************************
1028 * Module Resume for TSC2101
1030 ********************************************************************************/
1031 static int omap_tsc2101_resume(void)
1038 /*********************************************************************************
1040 * module_init for TSC2101
1042 ********************************************************************************/
1043 static int __init audio_tsc2101_init(void)
1049 if (machine_is_omap_osk() || machine_is_omap_innovator())
1052 /* register the codec with the audio driver */
1053 if ((err = audio_register_codec(&tsc2101_state))) {
1055 "Failed to register TSC driver with Audio OSS Driver\n");
1061 /*********************************************************************************
1063 * module_exit for TSC2101
1065 ********************************************************************************/
1066 static void __exit audio_tsc2101_exit(void)
1070 (void)audio_unregister_codec(&tsc2101_state);
1075 /**************************** DEBUG FUNCTIONS ***********************************/
1077 /*********************************************************************************
1079 * This is a test to generate various keyclick sound on tsc.
1080 * verifies if the tsc and the spi interfaces are operational.
1082 ********************************************************************************/
1083 #ifdef TEST_KEYCLICK
1084 void tsc2101_testkeyclick(void)
1087 u16 old_reg_val, reg_val;
1091 old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
1093 /* Keyclick active, max amplitude and longest key click len(32 period) */
1094 printk(KERN_INFO " TESTING KEYCLICK\n Listen carefully NOW....\n");
1095 printk(KERN_INFO " OLD REG VAL=0x%x\n", old_reg_val);
1096 /* try all frequencies */
1097 for (; freq < 8; freq++) {
1098 /* Keyclick active, max amplitude and longest key click len(32 period) */
1099 reg_val = old_reg_val | AC2_KCLAC(0x7) | AC2_KCLLN(0xF);
1102 printk(KERN_INFO "\n\nTrying frequency %d reg val= 0x%x\n",
1103 freq, reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1104 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2,
1105 reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1106 printk("DONE. Wait 10 ms ...\n");
1107 /* wait till the kclk bit is auto cleared! time out also to be considered. */
1108 while (audio_tsc2101_read(TSC2101_AUDIO_CTRL_2) & AC2_KCLEN) {
1111 if (uTryVal > 2000) {
1113 "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
1116 "uTryVal == %d: Read back new reg val= 0x%x\n",
1119 (TSC2101_AUDIO_CTRL_2));
1121 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
1126 /* put the old value back */
1127 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, old_reg_val);
1128 printk(KERN_INFO " KEYCLICK TEST COMPLETE\n");
1130 } /* End of tsc2101_testkeyclick */
1132 #endif /* TEST_KEYCLICK */
1134 /*********************************************************************************
1136 * This is a test to generate a rather unpleasant sound..
1137 * verifies if the mcbsp is active (requires MCBSP_DIRECT_RW to be active on McBSP)
1139 ********************************************************************************/
1141 /* Generates a shrill tone */
1143 0x0ce4, 0x0ce4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1144 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1145 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1146 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1147 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1148 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1149 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1150 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1151 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1152 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1153 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1154 0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1155 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1156 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1157 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1158 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1159 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1160 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1161 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1162 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1163 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1164 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1165 0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1166 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1167 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1168 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1169 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1170 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1171 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1172 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1173 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1174 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1175 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000
1182 printk(KERN_INFO "TONE GEN TEST :");
1184 for (count = 0; count < 5000; count++) {
1186 for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
1187 ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
1191 } else if (ret == -2) {
1192 printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
1197 printk(KERN_INFO "SUCCESS\n");
1200 #endif /* End of TONE_GEN */
1202 /*********************************************************************************
1204 * TSC_DUMP_REGISTERS:
1205 * This will dump the entire register set of Page 2 tsc2101.
1206 * Useful for major goof ups
1208 ********************************************************************************/
1209 #ifdef TSC_DUMP_REGISTERS
1210 static void tsc2101_dumpRegisters(void)
1214 printk("TSC 2101 Register dump for Page 2 \n");
1215 for (i = 0; i < 0x27; i++) {
1216 data = audio_tsc2101_read(i);
1217 printk(KERN_INFO "Register[%x]=0x%04x\n", i, data);
1221 #endif /* End of #ifdef TSC_DUMP_REGISTERS */
1224 static int codec_start(char *buf, char **start, off_t offset, int count,
1225 int *eof, void *data)
1227 omap_tsc2101_enable();
1229 printk("Codec initialization done.\n");
1232 static int codec_stop(char *buf, char **start, off_t offset, int count,
1233 int *eof, void *data)
1236 omap_tsc2101_disable();
1237 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
1238 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
1239 printk("Codec shutdown.\n");
1244 /*********************************************************************************
1246 * Other misc management, registration etc
1248 ********************************************************************************/
1249 module_init(audio_tsc2101_init);
1250 module_exit(audio_tsc2101_exit);
1252 MODULE_AUTHOR("Texas Instruments");
1254 ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
1255 MODULE_LICENSE("GPL");