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>
37 #include <asm/semaphore.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 CONFIG_ARCH_OMAP16XX
52 #include <../drivers/ssi/omap-uwire.h>
53 #include <asm/arch/dsp_common.h>
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 #if CONFIG_ARCH_OMAP16XX
74 #define PLATFORM_NAME "OMAP16XX"
77 #if CONFIG_ARCH_OMAP16XX
78 #define OMAP_DSP_BASE 0xE0000000
81 /* Define to set the tsc as the master w.r.t McBSP */
85 * AUDIO related MACROS
87 #define DEFAULT_BITPERSAMPLE 16
88 #define AUDIO_RATE_DEFAULT 44100
89 #define PAGE2_AUDIO_CODEC_REGISTERS (2)
92 /* Select the McBSP For Audio */
93 #if CONFIG_ARCH_OMAP16XX
94 #define AUDIO_MCBSP OMAP_MCBSP1
96 #error "UnSupported Configuration"
99 #define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
100 #define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME)
107 #define DEFAULT_VOLUME 93
108 #define DEFAULT_INPUT_VOLUME 20 /* An minimal volume */
110 /* Tsc Audio Specific */
111 #define NUMBER_SAMPLE_RATES_SUPPORTED 16
112 #define OUTPUT_VOLUME_MIN 0x7F
113 #define OUTPUT_VOLUME_MAX 0x32
114 #define OUTPUT_VOLUME_RANGE (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
115 #define OUTPUT_VOLUME_MASK OUTPUT_VOLUME_MIN
116 #define DEFAULT_VOLUME_LEVEL OUTPUT_VOLUME_MAX
118 /* use input vol of 75 for 0dB gain */
119 #define INPUT_VOLUME_MIN 0x0
120 #define INPUT_VOLUME_MAX 0x7D
121 #define INPUT_VOLUME_RANGE (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
122 #define INPUT_VOLUME_MASK INPUT_VOLUME_MAX
124 /*********** Debug Macros ********/
125 /* To Generate a rather shrill tone -test the entire path */
127 /* To Generate a tone for each keyclick - test the tsc,spi paths*/
128 //#define TEST_KEYCLICK
129 /* To dump the tsc registers for debug */
130 //#define TSC_DUMP_REGISTERS
139 #define DPRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
140 #define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
141 #define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
143 #define DPRINTK( x... )
148 /***************************** Data Structures **********************************/
150 static audio_stream_t output_stream = {
152 .dma_dev = OMAP_DMA_MCBSP1_TX,
153 .input_or_output = FMODE_WRITE
156 static audio_stream_t input_stream = {
158 .dma_dev = OMAP_DMA_MCBSP1_RX,
159 .input_or_output = FMODE_READ
162 static int audio_dev_id, mixer_dev_id;
170 } tsc2101_local_info;
172 static tsc2101_local_info tsc2101_local = {
173 volume: DEFAULT_VOLUME,
174 line: DEFAULT_INPUT_VOLUME,
175 mic: DEFAULT_INPUT_VOLUME,
176 recsrc: SOUND_MASK_LINE,
180 struct sample_rate_reg_info {
183 u8 fs_44kHz; /* if 0 48 khz, if 1 44.1 khz fsref */
186 /* To Store the default sample rate */
187 static long audio_samplerate = AUDIO_RATE_DEFAULT;
189 static const struct sample_rate_reg_info
190 reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
217 static struct omap_mcbsp_reg_cfg initial_config = {
218 .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
219 .spcr1 = RINTM(3) | RRST,
220 .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
221 RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
222 .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
223 .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
224 XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
225 .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
227 .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
229 /* platform specific initialization */
230 #if CONFIG_MACH_OMAP_H2
231 .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
232 #elif CONFIG_MACH_OMAP_H3
235 .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
237 .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
238 #endif /* tsc Master defs */
240 #endif /* platform specific inits */
243 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
245 static void omap_tsc2101_initialize(void *dummy);
247 static void omap_tsc2101_shutdown(void *dummy);
249 static int omap_tsc2101_ioctl(struct inode *inode, struct file *file,
250 uint cmd, ulong arg);
252 static int omap_tsc2101_probe(void);
254 static void omap_tsc2101_remove(void);
256 static int omap_tsc2101_suspend(void);
258 static int omap_tsc2101_resume(void);
260 static void tsc2101_configure(void);
262 static int mixer_open(struct inode *inode, struct file *file);
264 static int mixer_release(struct inode *inode, struct file *file);
266 static int mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
270 void tsc2101_testkeyclick(void);
277 #ifdef TSC_DUMP_REGISTERS
278 static void tsc2101_dumpRegisters(void);
282 static int codec_start(char *buf, char **start, off_t offset, int count,
283 int *eof, void *data);
285 static int codec_stop(char *buf, char **start, off_t offset, int count,
286 int *eof, void *data);
288 static void tsc2101_start(void);
291 /******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
293 /* File Op structure for mixer */
294 static struct file_operations omap_mixer_fops = {
296 .release = mixer_release,
297 .ioctl = mixer_ioctl,
301 /* To store characteristic info regarding the codec for the audio driver */
302 static audio_state_t tsc2101_state = {
303 .output_stream = &output_stream,
304 .input_stream = &input_stream,
305 /* .need_tx_for_rx = 1, //Once the Full Duplex works */
307 .hw_init = omap_tsc2101_initialize,
308 .hw_shutdown = omap_tsc2101_shutdown,
309 .client_ioctl = omap_tsc2101_ioctl,
310 .hw_probe = omap_tsc2101_probe,
311 .hw_remove = omap_tsc2101_remove,
312 .hw_suspend = omap_tsc2101_suspend,
313 .hw_resume = omap_tsc2101_resume,
314 .sem = __MUTEX_INITIALIZER(tsc2101_state.sem),
317 /* This will be defined in the Audio.h */
318 static struct file_operations *omap_audio_fops;
320 /***************************** MODULES SPECIFIC FUNCTIONs *******************************/
322 /*********************************************************************************
324 * Simplified write for tsc Audio
326 *********************************************************************************/
327 static __inline__ void audio_tsc2101_write(u8 address, u16 data)
329 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
332 /*********************************************************************************
334 * Simplified read for tsc Audio
336 *********************************************************************************/
337 static __inline__ u16 audio_tsc2101_read(u8 address)
339 return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
342 /*********************************************************************************
347 ********************************************************************************/
348 static int tsc2101_update(int flag, int val)
356 if (val < 0 || val > 100) {
357 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
360 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
362 ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
363 /* invert the value for getting the proper range 0 min and 100 max */
364 volume = OUTPUT_VOLUME_MIN - volume;
365 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
367 ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
368 DGC_DARVL(OUTPUT_VOLUME_MIN));
369 data |= DGC_DALVL(volume) | DGC_DARVL(volume);
370 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
371 data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
376 if (val < 0 || val > 100) {
377 printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
380 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
381 /* NOTE: 0 is minimum volume and not mute */
382 volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
383 /* Handset Input not muted, AGC for Handset In off */
384 audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
385 HGC_ADPGA_HED(volume));
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_HANDSET_GAIN_CTRL,
398 HNGC_ADPGA_HND(volume));
403 * If more than one recording device selected,
404 * disable the device that is currently in use.
406 if (hweight32(val) > 1)
407 val &= ~tsc2101_local.recsrc;
409 data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
410 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
412 if (val == SOUND_MASK_MIC) {
413 data |= MPC_MICSEL(1);
414 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
416 else if (val == SOUND_MASK_LINE) {
417 data |= MPC_MICSEL(0);
418 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
421 printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
422 " value specified\n");
425 tsc2101_local.recsrc = val;
428 printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
437 /*********************************************************************************
441 ********************************************************************************/
442 static int mixer_open(struct inode *inode, struct file *file)
444 /* Any mixer specific initialization */
446 /* Initalize the tsc2101 */
447 omap_tsc2101_enable();
452 /*********************************************************************************
456 ********************************************************************************/
457 static int mixer_release(struct inode *inode, struct file *file)
459 /* Any mixer specific Un-initialization */
460 omap_tsc2101_disable();
465 /*********************************************************************************
469 ********************************************************************************/
471 mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
476 int nr = _IOC_NR(cmd);
479 * We only accept mixer (type 'M') ioctls.
482 if (_IOC_TYPE(cmd) != 'M')
485 DPRINTK(" 0x%08x\n", cmd);
487 if (cmd == SOUND_MIXER_INFO) {
488 struct mixer_info mi;
490 strncpy(mi.id, "TSC2101", sizeof(mi.id));
491 strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
492 mi.modify_counter = tsc2101_local.mod_cnt;
494 return copy_to_user((void __user *)arg, &mi, sizeof(mi));
497 if (_IOC_DIR(cmd) & _IOC_WRITE) {
498 ret = get_user(val, (int __user *)arg);
502 /* Ignore separate left/right channel for now,
503 * even the codec does support it.
508 case SOUND_MIXER_VOLUME:
509 tsc2101_local.volume = val;
510 tsc2101_local.mod_cnt++;
511 ret = tsc2101_update(SET_VOLUME, gain);
514 case SOUND_MIXER_LINE:
515 tsc2101_local.line = val;
516 tsc2101_local.mod_cnt++;
517 ret = tsc2101_update(SET_LINE, gain);
520 case SOUND_MIXER_MIC:
521 tsc2101_local.mic = val;
522 tsc2101_local.mod_cnt++;
523 ret = tsc2101_update(SET_MIC, gain);
526 case SOUND_MIXER_RECSRC:
527 if ((val & SOUND_MASK_LINE) ||
528 (val & SOUND_MASK_MIC)) {
529 if (tsc2101_local.recsrc != val) {
530 tsc2101_local.mod_cnt++;
531 tsc2101_update(SET_RECSRC, val);
544 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
548 case SOUND_MIXER_VOLUME:
549 val = tsc2101_local.volume;
550 val = (tsc2101_local.volume << 8) |
551 tsc2101_local.volume;
553 case SOUND_MIXER_LINE:
554 val = (tsc2101_local.line << 8) |
557 case SOUND_MIXER_MIC:
558 val = (tsc2101_local.mic << 8) |
561 case SOUND_MIXER_RECSRC:
562 val = tsc2101_local.recsrc;
564 case SOUND_MIXER_RECMASK:
567 case SOUND_MIXER_DEVMASK:
570 case SOUND_MIXER_CAPS:
573 case SOUND_MIXER_STEREODEVS:
574 val = SOUND_MASK_VOLUME;
578 printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
579 "read ioctl flag specified\n");
585 ret = put_user(val, (int __user *)arg);
593 /*********************************************************************************
595 * omap_set_samplerate()
597 ********************************************************************************/
598 static int omap_set_samplerate(long sample_rate)
603 /* wait for any frame to complete */
606 /* Search for the right sample rate */
607 while ((reg_info[count].sample_rate != sample_rate) &&
608 (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
611 if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
612 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
618 data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
619 /*Clear prev settings */
620 data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
622 AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
624 audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
627 data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
628 /*Clear prev settings */
629 data &= ~(AC3_REFFS | AC3_SLVMS);
630 data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
633 #endif /* #ifdef TSC_MASTER */
634 audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
636 /* program the PLLs */
637 if (reg_info[count].fs_44kHz) {
638 /* 44.1 khz - 12 MHz Mclk */
639 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */
640 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */
642 /* 48 khz - 12 Mhz Mclk */
643 audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */
644 audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */
647 audio_samplerate = sample_rate;
649 /* Set the sample rate */
652 DEFAULT_MCBSP_CLOCK / (sample_rate *
653 (DEFAULT_BITPERSAMPLE * 2 - 1));
655 initial_config.srgr1 =
656 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
661 initial_config.srgr2 =
662 (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
664 initial_config.srgr1 =
665 (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
666 initial_config.srgr2 =
667 ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
669 #endif /* end of #ifdef TSC_MASTER */
670 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
675 /*********************************************************************************
677 * omap_tsc2101_initialize() [hw_init() ]
679 ********************************************************************************/
680 static void omap_tsc2101_initialize(void *dummy)
683 DPRINTK("omap_tsc2101_initialize entry\n");
685 /* initialize with default sample rate */
686 audio_samplerate = AUDIO_RATE_DEFAULT;
688 omap_mcbsp_request(AUDIO_MCBSP);
690 /* if configured, then stop mcbsp */
691 omap_mcbsp_stop(AUDIO_MCBSP);
693 omap_tsc2101_enable();
695 omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
696 omap_mcbsp_start(AUDIO_MCBSP);
700 tsc2101_testkeyclick();
707 DPRINTK("omap_tsc2101_initialize exit\n");
710 /*********************************************************************************
712 * omap_tsc2101_shutdown() [hw_shutdown() ]
714 ********************************************************************************/
715 static void omap_tsc2101_shutdown(void *dummy)
718 Turn off codec after it is done.
719 Can't do it immediately, since it may still have
722 Wait 20ms (arbitrary value) and then turn it off.
726 set_current_state(TASK_INTERRUPTIBLE);
729 omap_mcbsp_stop(AUDIO_MCBSP);
730 omap_mcbsp_free(AUDIO_MCBSP);
732 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
733 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
735 omap_tsc2101_disable();
740 /*********************************************************************************
744 ********************************************************************************/
745 static void tsc2101_configure(void)
749 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
751 /*Mute Analog Sidetone */
752 /*Select MIC_INHED input for headset */
753 /*Cell Phone In not connected */
754 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
755 MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
757 /* Set record source */
758 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
760 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
761 /* 1dB AGC hysteresis */
763 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
765 /* Set codec output volume */
766 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
768 /* DAC left and right routed to SPK2 */
770 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
771 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
772 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
775 /* OUT8P/N muted, CPOUT muted */
777 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
778 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
781 /* Headset/Hook switch detect disabled */
782 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
784 /* Left line input volume control */
785 tsc2101_update(SET_LINE, tsc2101_local.line);
787 /* mic input volume control */
788 tsc2101_update(SET_MIC, tsc2101_local.mic);
790 /* Left/Right headphone channel volume control */
791 /* Zero-cross detect on */
792 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
794 /* clock configuration */
795 omap_set_samplerate(audio_samplerate);
797 #ifdef TSC_DUMP_REGISTERS
798 tsc2101_dumpRegisters();
805 static void tsc2101_start(void)
809 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
811 /*Mute Analog Sidetone */
812 /*Select MIC_INHED input for headset */
813 /*Cell Phone In not connected */
814 audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
815 MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
817 /* Set record source */
818 tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
820 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
821 /* 1dB AGC hysteresis */
823 audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
825 /* Set codec output volume */
826 audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
828 /* DAC left and right routed to SPK2 */
830 audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
831 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
832 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
835 /* OUT8P/N muted, CPOUT muted */
837 audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
838 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
841 /* Headset/Hook switch detect disabled */
842 audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
844 /* Left line input volume control */
845 tsc2101_update(SET_LINE, tsc2101_local.line);
847 /* mic input volume control */
848 tsc2101_update(SET_MIC, tsc2101_local.mic);
850 /* Left/Right headphone channel volume control */
851 /* Zero-cross detect on */
852 tsc2101_update(SET_VOLUME, tsc2101_local.volume);
859 /******************************************************************************************
861 * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
862 * routine handles some platform specific ioctl's
864 ******************************************************************************************/
866 omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
871 DPRINTK(" 0x%08x\n", cmd);
874 * These are platform dependent ioctls which are not handled by the
875 * generic omap-audio module.
878 case SNDCTL_DSP_STEREO:
879 ret = get_user(val, (int __user *)arg);
882 /* the AIC23 is stereo only */
883 ret = (val == 0) ? -EINVAL : 1;
885 return put_user(ret, (int __user *)arg);
887 case SNDCTL_DSP_CHANNELS:
888 case SOUND_PCM_READ_CHANNELS:
889 /* the AIC23 is stereo only */
891 return put_user(2, (long __user *)arg);
893 case SNDCTL_DSP_SPEED:
894 ret = get_user(val, (long __user *)arg);
897 ret = omap_set_samplerate(val);
902 case SOUND_PCM_READ_RATE:
904 return put_user(audio_samplerate, (long __user *)arg);
906 case SOUND_PCM_READ_BITS:
907 case SNDCTL_DSP_SETFMT:
908 case SNDCTL_DSP_GETFMTS:
909 /* we can do 16-bit only */
911 return put_user(AFMT_S16_LE, (long __user *)arg);
914 /* Maybe this is meant for the mixer (As per OSS Docs) */
916 return mixer_ioctl(inode, file, cmd, arg);
923 /*********************************************************************************
925 * module_probe for TSC2101
927 ********************************************************************************/
928 static int omap_tsc2101_probe(void)
932 /* Get the fops from audio oss driver */
933 if (!(omap_audio_fops = audio_get_fops())) {
934 printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
935 audio_unregister_codec(&tsc2101_state);
939 /* register devices */
940 audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
941 mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
944 create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
945 NULL /* parent dir */ ,
946 codec_start, NULL /* client data */ );
948 create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
949 NULL /* parent dir */ ,
950 codec_stop, NULL /* client data */ );
953 /* Announcement Time */
954 printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
955 " Audio support initialized\n");
961 /*********************************************************************************
963 * Module Remove for TSC2101
965 ********************************************************************************/
966 static void omap_tsc2101_remove(void)
969 /* Un-Register the codec with the audio driver */
970 unregister_sound_dsp(audio_dev_id);
971 unregister_sound_mixer(mixer_dev_id);
974 remove_proc_entry(PROC_START_FILE, NULL);
975 remove_proc_entry(PROC_STOP_FILE, NULL);
981 /*********************************************************************************
983 * Module Suspend for TSC2101
985 ********************************************************************************/
986 static int omap_tsc2101_suspend(void)
993 /*********************************************************************************
995 * Module Resume for TSC2101
997 ********************************************************************************/
998 static int omap_tsc2101_resume(void)
1005 /*********************************************************************************
1007 * module_init for TSC2101
1009 ********************************************************************************/
1010 static int __init audio_tsc2101_init(void)
1016 if (machine_is_omap_osk() || machine_is_omap_innovator())
1019 /* register the codec with the audio driver */
1020 if ((err = audio_register_codec(&tsc2101_state))) {
1022 "Failed to register TSC driver with Audio OSS Driver\n");
1028 /*********************************************************************************
1030 * module_exit for TSC2101
1032 ********************************************************************************/
1033 static void __exit audio_tsc2101_exit(void)
1037 (void)audio_unregister_codec(&tsc2101_state);
1042 /**************************** DEBUG FUNCTIONS ***********************************/
1044 /*********************************************************************************
1046 * This is a test to generate various keyclick sound on tsc.
1047 * verifies if the tsc and the spi interfaces are operational.
1049 ********************************************************************************/
1050 #ifdef TEST_KEYCLICK
1051 void tsc2101_testkeyclick(void)
1054 u16 old_reg_val, reg_val;
1058 old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
1060 /* Keyclick active, max amplitude and longest key click len(32 period) */
1061 printk(KERN_INFO " TESTING KEYCLICK\n Listen carefully NOW....\n");
1062 printk(KERN_INFO " OLD REG VAL=0x%x\n", old_reg_val);
1063 /* try all frequencies */
1064 for (; freq < 8; freq++) {
1065 /* Keyclick active, max amplitude and longest key click len(32 period) */
1066 reg_val = old_reg_val | AC2_KCLAC(0x7) | AC2_KCLLN(0xF);
1069 printk(KERN_INFO "\n\nTrying frequency %d reg val= 0x%x\n",
1070 freq, reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1071 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2,
1072 reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
1073 printk("DONE. Wait 10 ms ...\n");
1074 /* wait till the kclk bit is auto cleared! time out also to be considered. */
1075 while (audio_tsc2101_read(TSC2101_AUDIO_CTRL_2) & AC2_KCLEN) {
1078 if (uTryVal > 2000) {
1080 "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
1083 "uTryVal == %d: Read back new reg val= 0x%x\n",
1086 (TSC2101_AUDIO_CTRL_2));
1088 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
1093 /* put the old value back */
1094 audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, old_reg_val);
1095 printk(KERN_INFO " KEYCLICK TEST COMPLETE\n");
1097 } /* End of tsc2101_testkeyclick */
1099 #endif /* TEST_KEYCLICK */
1101 /*********************************************************************************
1103 * This is a test to generate a rather unpleasant sound..
1104 * verifies if the mcbsp is active (requires MCBSP_DIRECT_RW to be active on McBSP)
1106 ********************************************************************************/
1108 /* Generates a shrill tone */
1110 0x0ce4, 0x0ce4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1111 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1112 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1113 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1114 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1115 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1116 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1117 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1118 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1119 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1120 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1121 0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1122 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1123 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1124 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1125 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1126 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1127 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1128 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1129 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1130 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1131 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
1132 0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
1133 0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
1134 0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
1135 0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
1136 0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
1137 0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
1138 0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
1139 0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
1140 0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
1141 0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
1142 0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000
1149 printk(KERN_INFO "TONE GEN TEST :");
1151 for (count = 0; count < 5000; count++) {
1153 for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
1154 ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
1158 } else if (ret == -2) {
1159 printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
1164 printk(KERN_INFO "SUCCESS\n");
1167 #endif /* End of TONE_GEN */
1169 /*********************************************************************************
1171 * TSC_DUMP_REGISTERS:
1172 * This will dump the entire register set of Page 2 tsc2101.
1173 * Useful for major goof ups
1175 ********************************************************************************/
1176 #ifdef TSC_DUMP_REGISTERS
1177 static void tsc2101_dumpRegisters(void)
1181 printk("TSC 2101 Register dump for Page 2 \n");
1182 for (i = 0; i < 0x27; i++) {
1183 data = audio_tsc2101_read(i);
1184 printk(KERN_INFO "Register[%x]=0x%04x\n", i, data);
1188 #endif /* End of #ifdef TSC_DUMP_REGISTERS */
1191 static int codec_start(char *buf, char **start, off_t offset, int count,
1192 int *eof, void *data)
1194 omap_tsc2101_enable();
1196 printk("Codec initialization done.\n");
1199 static int codec_stop(char *buf, char **start, off_t offset, int count,
1200 int *eof, void *data)
1203 omap_tsc2101_disable();
1204 audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
1205 ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
1206 printk("Codec shutdown.\n");
1211 /*********************************************************************************
1213 * Other misc management, registration etc
1215 ********************************************************************************/
1216 module_init(audio_tsc2101_init);
1217 module_exit(audio_tsc2101_exit);
1219 MODULE_AUTHOR("Texas Instruments");
1221 ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
1222 MODULE_LICENSE("GPL");