📄 omap-audio-tsc2101.c
字号:
/* * linux/sound/oss/omap-audio-tsc2101.c * * Glue driver for TSC2101 for OMAP processors * * Copyright (C) 2004 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * History: * ------- * 2004-08-12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 * and 2420 platforms. * 2004-09-14 Sriram Kannan - Added /proc support for asynchronous starting/stopping the codec * (without affecting the normal driver flow). * 2004-10-20 Nishanth Menon - Fixed issue of Mixer operations in 2420. * 2004-11-04 Nishanth Menon - Support for power management * 2004-11-07 Nishanth Menon - Support for Common TSC access b/w Touchscreen and audio drivers *//***************************** INCLUDES ************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/errno.h>#include <linux/sound.h>#include <linux/soundcard.h>#include <asm/semaphore.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/arch/dma.h>#include <asm/io.h>#include <asm/hardware.h>#include <asm/arch/mux.h>#include <asm/arch/io.h>#include "omap-audio.h"#include "omap-audio-dma-intfc.h"#include <../drivers/ssi/omap-mcbsp.h>#if CONFIG_ARCH_OMAP16XX#include <asm/arch/clocks.h>#include <../drivers/ssi/omap-uwire.h>#elif CONFIG_ARCH_OMAP24XX#include <../drivers/ssi/omap-mcspi.h>#endif#include <asm/hardware/tsc2101.h>#include <../drivers/ssi/omap-tsc2101.h>/***************************** MACROS ************************************/#define PROC_SUPPORT#ifdef PROC_SUPPORT#include <linux/proc_fs.h>#define PROC_START_FILE "driver/tsc2101-audio-start"#define PROC_STOP_FILE "driver/tsc2101-audio-stop"#endif#define CODEC_NAME "TSC2101"#if CONFIG_ARCH_OMAP16XX#define PLATFORM_NAME "OMAP16XX"#define DMA_TX OMAP_DMA_MCBSP1_TX#define DMA_RX OMAP_DMA_MCBSP1_RX#elif CONFIG_ARCH_OMAP24XX#define PLATFORM_NAME "OMAP24xx"#define DMA_TX eAudioTx#define DMA_RX eAudioRx#endif/* Define to set the tsc as the master w.r.t McBSP */#define TSC_MASTER/* * AUDIO related MACROS */#define DEFAULT_BITPERSAMPLE 16#define AUDIO_RATE_DEFAULT 44100#define PAGE2_AUDIO_CODEC_REGISTERS (2)#define LEAVE_CS 0x80/* Select the McBSP For Audio */#if CONFIG_ARCH_OMAP16XX#define AUDIO_MCBSP OMAP_MCBSP1#elif CONFIG_ARCH_OMAP24XX#define AUDIO_MCBSP OMAP_MCBSP2#else#error "UnSupported Configuration"#endif#define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)#define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME)#define SET_VOLUME 1#define SET_LINE 2#define DEFAULT_VOLUME 93#define DEFAULT_INPUT_VOLUME 0 /* 0 ==> mute line in *//* Tsc Audio Specific */#define NUMBER_SAMPLE_RATES_SUPPORTED 16#define OUTPUT_VOLUME_MIN 0x7F#define OUTPUT_VOLUME_MAX 0x32#define OUTPUT_VOLUME_RANGE (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)#define OUTPUT_VOLUME_MASK OUTPUT_VOLUME_MIN#define DEFAULT_VOLUME_LEVEL OUTPUT_VOLUME_MAX/* use input vol of 75 for 0dB gain */#define INPUT_VOLUME_MIN 0x0#define INPUT_VOLUME_MAX LIV_MAX#define INPUT_VOLUME_RANGE (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)#define INPUT_VOLUME_MASK INPUT_VOLUME_MAX/*********** Debug Macros ********//* To Generate a rather shrill tone -test the entire path *///#define TONE_GEN/* To Generate a tone for each keyclick - test the tsc,spi paths*///#define TEST_KEYCLICK/* To dump the tsc registers for debug *///#define TSC_DUMP_REGISTERS#ifdef DPRINTK#undef DPRINTK#endif#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)#else#define DPRINTK( x... )#define FN_IN#define FN_OUT(n)#endif/***************************** Data Structures **********************************/static audio_stream_t output_stream = { .id = "TSC2101 out", .dma_dev = DMA_TX, .input_or_output = FMODE_WRITE};static audio_stream_t input_stream = { .id = "TSC2101 in", .dma_dev = DMA_RX, .input_or_output = FMODE_READ};static int audio_dev_id, mixer_dev_id;static struct tsc_local_info { u8 volume; u16 volume_reg; u8 line; u8 mic; u16 input_volume_reg; int mod_cnt;} tsc2101_local;struct sample_rate_reg_info { u16 sample_rate; u8 divisor; u8 fs_44kHz; /* if 0 48 khz, if 1 44.1 khz fsref */};/* To Store the default sample rate */static long audio_samplerate = AUDIO_RATE_DEFAULT;static const struct sample_rate_reg_info reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = { /* Div 1 */ {48000, 0, 0}, {44100, 0, 1}, /* Div 1.5 */ {32000, 1, 0}, {29400, 1, 1}, /* Div 2 */ {24000, 2, 0}, {22050, 2, 1}, /* Div 3 */ {16000, 3, 0}, {14700, 3, 1}, /* Div 4 */ {12000, 4, 0}, {11025, 4, 1}, /* Div 5 */ {9600, 5, 0}, {8820, 5, 1}, /* Div 5.5 */ {8727, 6, 0}, {8018, 6, 1}, /* Div 6 */ {8000, 7, 0}, {7350, 7, 1},};/***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/static void omap_tsc2101_initialize(void *dummy);static void omap_tsc2101_shutdown(void *dummy);static int omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg);static int omap_tsc2101_probe(void);static void omap_tsc2101_remove(void);static int omap_tsc2101_suspend(void);static int omap_tsc2101_resume(void);static inline void tsc2101_configure(void);static int mixer_open(struct inode *inode, struct file *file);static int mixer_release(struct inode *inode, struct file *file);static int mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg);#ifdef TEST_KEYCLICKvoid tsc2101_testkeyclick(void);#endif#ifdef TONE_GENvoid toneGen(void);#endif#ifdef TSC_DUMP_REGISTERSstatic void tsc2101_dumpRegisters(void);#endif#ifdef PROC_SUPPORTstatic int codec_start(char *buf, char **start, off_t offset, int count, int *eof, void *data);static int codec_stop(char *buf, char **start, off_t offset, int count, int *eof, void *data);static void tsc2101_start(void);#endif/******************** DATA STRUCTURES USING FUNCTION POINTERS **************************//* File Op structure for mixer */static struct file_operations omap_mixer_fops = { .open = mixer_open, .release = mixer_release, .ioctl = mixer_ioctl, .owner = THIS_MODULE};/* To store characteristic info regarding the codec for the audio driver */static audio_state_t tsc2101_state = { .output_stream = &output_stream, .input_stream = &input_stream,/* .need_tx_for_rx = 1, //Once the Full Duplex works */ .need_tx_for_rx = 0, .hw_init = omap_tsc2101_initialize, .hw_shutdown = omap_tsc2101_shutdown, .client_ioctl = omap_tsc2101_ioctl, .hw_probe = omap_tsc2101_probe, .hw_remove = omap_tsc2101_remove, .hw_suspend = omap_tsc2101_suspend, .hw_resume = omap_tsc2101_resume, .sem = __MUTEX_INITIALIZER(tsc2101_state.sem),};/* This will be defined in the Audio.h */static struct file_operations *omap_audio_fops;/***************************** MODULES SPECIFIC FUNCTIONs *******************************//********************************************************************************* * * Simplified write for tsc Audio * *********************************************************************************/static __inline__ void audio_tsc2101_write(u8 address, u16 data){ omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);}/********************************************************************************* * * Simplified read for tsc Audio * *********************************************************************************/static __inline__ u16 audio_tsc2101_read(u8 address){ return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));}/********************************************************************************* * * tsc2101_update() * Volume Adj etc * ********************************************************************************/static int tsc2101_update(int flag, int val){ u16 volume; u16 data; FN_IN; switch (flag) { case SET_VOLUME: if (val < 0 || val > 100) { printk(KERN_ERR "Trying a bad volume value(%d)!\n", val); return -EPERM; } /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */ volume = ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX; /* invert the value for getting the proper range 0 min and 100 max */ volume = OUTPUT_VOLUME_MIN - volume; data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL); data &= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) | DGC_DARVL(OUTPUT_VOLUME_MIN)); data |= DGC_DALVL(volume) | DGC_DARVL(volume); audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data); data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL); break; case SET_LINE: /* Not implemented yet */ break; } FN_OUT(0); return 0;}/********************************************************************************* * * mixer_open() * ********************************************************************************/static int mixer_open(struct inode *inode, struct file *file){ /* Any mixer specific initialization */ /* Initalize the tsc2101 */ omap_tsc2101_enable(); return 0;}/********************************************************************************* * * mixer_release()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -