diff options
Diffstat (limited to 'packages/linux/linux-ezx/ezx_sound.patch')
-rw-r--r-- | packages/linux/linux-ezx/ezx_sound.patch | 6874 |
1 files changed, 6874 insertions, 0 deletions
diff --git a/packages/linux/linux-ezx/ezx_sound.patch b/packages/linux/linux-ezx/ezx_sound.patch new file mode 100644 index 0000000000..7a3b609e51 --- /dev/null +++ b/packages/linux/linux-ezx/ezx_sound.patch @@ -0,0 +1,6874 @@ +Sound support for EZX platform + +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-a780.c linux-2.6.16.5-exz/sound/oss/ezx-a780.c +--- linux-2.6.16.5/sound/oss/ezx-a780.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-a780.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,530 @@ ++/* ++ * linux/drivers/sound/ezx-a780.c ++ * ++ * ++ * Description: Motorola a780 phone specific functions implementation for audio drivers ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Created, Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * Jin Lihong(w20076) Jun.22,2004,LIBee24284 mixer power save ++ * Cheng Xuefeng(a2491c) Jun.24,2004,LIBdd95397 Add EMU PIHF carkit sound path ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-common.h" ++ ++ ++#ifdef CONFIG_ARCH_EZX_A780 ++ ++extern u32 gpio_hw_attenuate_a780_status; ++ ++ ++void close_input_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input carkit. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++#if EMU_PIHF_FEATURE ++void close_input_pihf_carkit(void) ++{ ++ printk("EMU:%s,%s\n",__FILE__,__FUNCTION__); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++#endif /* EMU_PIHF_FEATURE */ ++ ++ ++void close_input_handset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input handset. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON1); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_MUX); ++} ++ ++ ++void close_input_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input headset. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_MUX); ++} ++ ++ ++void open_input_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input carkit. \n"); ++#endif ++ ++ codec_input_path = CARKIT_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++#if EMU_PIHF_FEATURE ++void open_input_pihf_carkit(void) ++{ ++ printk("EMU:%s,%s\n",__FILE__,__FUNCTION__); ++ codec_input_path = PIHF_CARKIT_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++#endif /* EMU_PIHF_FEATURE */ ++ ++ ++void open_input_handset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input handset. \n"); ++#endif ++ ++ codec_input_path = HANDSET_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON1); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_MUX); ++} ++ ++ ++void open_input_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input headset. \n"); ++#endif ++ ++ codec_input_path = HEADSET_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_MUX); ++} ++ ++ ++void close_output_pcap_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap headset. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++} ++ ++ ++void close_output_pcap_louderspeaker(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap louderspeaker. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A2_EN); ++} ++ ++ ++void close_output_pcap_earpiece(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap earpiece. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1_EN); ++} ++ ++ ++void close_output_pcap_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap carkit. \n"); ++#endif ++ EIHF_Mute(EIHF_MUTE); //Mute EIHF ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ++ Set_EMU_Mux_Switch(DEFAULT_USB_MODE); ++} ++ ++ ++#if EMU_PIHF_FEATURE ++void close_output_pcap_pihf_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap pihf carkit. \n"); ++ printk("EMU:%s,%s\n",__FILE__,__FUNCTION__); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++} ++#endif /* EMU_PIHF_FEATURE */ ++ ++ ++void close_output_pcap_headjack(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap headjack. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++} ++ ++ ++void close_output_pcap_bluetooth(void) ++{ ++} ++ ++ ++int open_output_pcap_headset(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap headset. \n"); ++#endif ++ ++ if((audioonflag & DSP_DEVICE)==DSP_DEVICE) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ codec_output_path = val; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_louderspeaker(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap louderspeaker. \n"); ++#endif ++ ++ if((audioonflag & DSP_DEVICE)==DSP_DEVICE) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ codec_output_path = val; ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A2_EN); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_earpiece(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap earpiece. \n"); ++#endif ++ ++ if((audioonflag & DSP_DEVICE)==DSP_DEVICE) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ codec_output_path = val; ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1_EN); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_carkit(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap carkit. \n"); ++#endif ++ ++ Set_EMU_Mux_Switch(MONO_AUDIO_MODE); ++ ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ ++ codec_output_path = val; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ++ set_output_gain_hw_reg(); ++ ++ EIHF_Mute(EIHF_UNMUTE); ++ ++ return ret; ++} ++ ++ ++#if EMU_PIHF_FEATURE ++int open_output_pcap_pihf_carkit(long val) ++{ ++ int ret; ++ ++ printk("EMU:%s,%s\n",__FILE__,__FUNCTION__); ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ ++ codec_output_path = val; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++#endif /* EMU_PIHF_FEATURE */ ++ ++ ++int open_output_pcap_headjack(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap headjack. \n"); ++#endif ++ ++ if((audioonflag & DSP_DEVICE)==DSP_DEVICE) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ codec_output_path = val; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_bluetooth(long val) ++{ ++ return 0; ++} ++ ++ ++void set_output_gain_hw_reg(void) ++{ ++ SSP_PCAP_AUDOG_set( PCAP_OUTPUT_GAIN_REG_VAL_FROM_LOGIC ); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_output_gain=%d\n", codec_output_gain); ++ printk(EZXOSS_DEBUG "output gain=%d\n",PCAP_OUTPUT_GAIN_REG_VAL_FROM_LOGIC); ++#endif ++} ++ ++ ++void set_input_gain_hw_reg(void) ++{ ++ SSP_PCAP_AUDIG_set( PCAP_INPUT_AUDIG_REG_VAL_FROM_LOGIC ); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_input_gain=%d\n", codec_input_gain); ++#endif ++} ++ ++ ++void poweron_mixer( audio_dev_type type ) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device wants to power on the mixer hardware.\n", type); ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device has already powered on the mixer hardware.\n", audioonflag); ++#endif ++ ++ audioonflag |= type; ++ if( audioonflag == type ) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device is powering on the mixer hardware.\n", type); ++#endif ++ ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++ ++ /* (1) set pcap audio power V2_EN_2(OR WITH V2_EN) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ ++ /* (6) enable output_path and set gain */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP); /* disable codec bypass */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ST_DAC_SW); /* close stereo switch */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CDC_SW); /* open telephone codec path into right PGA */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); /* close PGA_INR into PGA */ ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN); /* enable right PGA */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); /* enable left PGA */ ++ } ++} ++ ++ ++void shutdown_mixer( audio_dev_type type ) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device wants to shut down the mixer hardware.\n", type); ++#endif ++ ++ audioonflag &= ~type; ++ ++ if( audioonflag == 0 ) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device is shutting down the mixer hardware.\n", type); ++#endif ++ /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER, SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ } ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "A780 No. 0x%X device is still using the mixer hardware.\n", audioonflag); ++#endif ++} ++ ++ ++void mixer_not_in_use(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " A780 mixer not in use.\n"); ++#endif ++ ++ (*mixer_close_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(); ++ (*mixer_close_input_path[codec_input_path])(); ++ ++ if( micinflag == 0 ) /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER, SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++} ++ ++ ++u32 gpio_hw_attenuate_a780_status; ++void use_hw_noise_attenuate(void) ++{ ++ set_GPIO_mode(GPIO_HW_ATTENUATE_A780 | GPIO_OUT); ++ clr_GPIO(GPIO_HW_ATTENUATE_A780); ++ PGSR(GPIO_HW_ATTENUATE_A780) &= ~GPIO_bit(GPIO_HW_ATTENUATE_A780); ++ gpio_hw_attenuate_a780_status = 0; ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "set a780 hw noise attenuation gpio low. \n"); ++#endif ++} ++ ++ ++void bypass_hw_noise_attenuate(void) ++{ ++ set_GPIO_mode(GPIO_HW_ATTENUATE_A780 | GPIO_OUT); ++ set_GPIO(GPIO_HW_ATTENUATE_A780); ++ PGSR(GPIO_HW_ATTENUATE_A780) |= GPIO_bit(GPIO_HW_ATTENUATE_A780); ++ gpio_hw_attenuate_a780_status = 1; ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "set a780 hw noise attenuation gpio high. \n"); ++#endif ++} ++ ++ ++void pcap_use_ap_13m_clock(void) ++{ ++ OSCC |= 0x00000008; ++ set_GPIO_mode(AP_13MHZ_OUTPUT_PIN | GPIO_ALT_FN_3_OUT); ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_CLK_IN_SEL); ++} ++ ++ ++void pcap_use_bp_13m_clock(void) ++{ ++ OSCC &= ~0x00000008; ++ set_GPIO_mode(AP_13MHZ_OUTPUT_PIN | GPIO_IN); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_CLK_IN_SEL); ++} ++ ++ ++#ifdef CONFIG_PM ++int mixer_hw_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ switch(req){ ++ case PM_SUSPEND: ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " A780 before AP sleep.\n"); ++#endif ++ if( (audioonflag & PHONE_DEVICE) == 0 ) ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ break; ++ case PM_RESUME: ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " A780 after AP sleep.\n"); ++#endif ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ set_output_gain_hw_reg(); ++ ++ if(gpio_hw_attenuate_a780_status) ++ bypass_hw_noise_attenuate(); ++ else ++ use_hw_noise_attenuate(); ++ if(audioonflag) ++ (*mixer_open_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(codec_output_base|codec_output_path); ++ ++ break; ++ } ++ return 0; ++} ++#endif ++ ++ ++void mute_output_to_avoid_pcap_noise(void) ++{ ++} ++ ++ ++void undo_mute_output_to_avoid_pcap_noise(void) ++{ ++} ++ ++ ++#endif ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-a780.h linux-2.6.16.5-exz/sound/oss/ezx-a780.h +--- linux-2.6.16.5/sound/oss/ezx-a780.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-a780.h 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,117 @@ ++/* ++ * linux/drivers/sound/ezx-a780.h ++ * ++ * ++ * Description: header file for ezx-a780.c ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Created, Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * Jin Lihong(w20076) Jun.22,2004,LIBee24284 mixer power save ++ * Cheng Xuefeng(a2491c) Jun.24,2004,LIBdd95397 Add EMU PIHF carkit sound path ++ * ++ */ ++ ++#ifndef EZX_A780_H ++#define EZX_A780_H ++ ++#include <linux/config.h> ++ ++#ifdef CONFIG_ARCH_EZX_A780 ++ ++//#define EZX_OSS_DEBUG /* debug switch for all ezx oss src files excluding ezx-audio.c */ ++#undef EZX_OSS_DEBUG ++//#define EZX_OSS_AUDIO_DEBUG /* debug switch for src file ezx-audio.c */ ++#undef EZX_OSS_AUDIO_DEBUG ++ ++/* ++#ifdef EZX_OSS_DBG ++#define OSSPRINTF(fmt,args...) printf(fmt,##args) ++#else ++#define OSSPRINTF(fmt,args...) { } ++#endif ++*/ ++ ++ ++typedef enum{ ++ PHONE_DEVICE = 0x01, ++ DSP_DEVICE = 0x02, ++ DSP16_DEVICE = 0x04, ++ AUDIO_DEVICE = 0x08 ++}audio_dev_type; ++ ++typedef enum{ ++ HW_ATTENUATION_USED, ++ HW_ATTENUATION_BYPASSED ++}hw_noise_attenuation; ++ ++ ++void close_input_carkit(void); ++void close_input_handset(void); ++void close_input_headset(void); ++#if EMU_PIHF_FEATURE ++void close_input_pihf_carkit(void); ++#endif ++ ++void open_input_carkit(void); ++void open_input_handset(void); ++void open_input_headset(void); ++#if EMU_PIHF_FEATURE ++void open_input_pihf_carkit(void); ++#endif ++ ++void close_output_pcap_headset(void); ++void close_output_pcap_louderspeaker(void); ++void close_output_pcap_earpiece(void); ++void close_output_pcap_carkit(void); ++void close_output_pcap_headjack(void); ++void close_output_pcap_bluetooth(void); ++#if EMU_PIHF_FEATURE ++void close_output_pcap_pihf_carkit(void); ++#endif ++ ++int open_output_pcap_headset(long val); ++int open_output_pcap_louderspeaker(long val); ++int open_output_pcap_earpiece(long val); ++int open_output_pcap_carkit(long val); ++int open_output_pcap_headjack(long val); ++int open_output_pcap_bluetooth(long val); ++#if EMU_PIHF_FEATURE ++int open_output_pcap_pihf_carkit(long val); ++#endif ++ ++void set_output_gain_hw_reg(void); ++void set_input_gain_hw_reg(void); ++ ++void poweron_mixer( audio_dev_type type ); ++void shutdown_mixer( audio_dev_type type ); ++void mixer_not_in_use(void); ++ ++void use_hw_noise_attenuate(void); ++void bypass_hw_noise_attenuate(void); ++ ++void pcap_use_ap_13m_clock(void); ++void pcap_use_bp_13m_clock(void); ++ ++void mute_output_to_avoid_pcap_noise(void); ++void undo_mute_output_to_avoid_pcap_noise(void); ++ ++int mixer_hw_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data); ++ ++#endif ++ ++ ++#endif ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-asspm.c linux-2.6.16.5-exz/sound/oss/ezx-asspm.c +--- linux-2.6.16.5/sound/oss/ezx-asspm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-asspm.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,550 @@ ++/* ++ * linux/drivers/sound/ezx-asspm.c ++ * ++ * ++ * Description: assp interface for the ezx platform ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhouqiong Jun 20,2002 created ++ * zhouqiong Sep 19,2002 according code review meeting minutes. ++ * zhouqiong Oct 30,2002 according new requirement for VA.ASSP interface split to ++ * /dev/dsp (support stereo playback) and /dev/dsp16 (support ++ * mono playback and record).this file is for mono playback and record ++ * zhouqiong Nov 05,2002 according code review meeting minutes. ++ * zhouqiong Mar 04,2003 (1) don't close headset interrupt; ++ * (2) when headset in, output gain decrease 6db ++ * zhouqiong Apr 24,2003 no switch for headset insert and remove ++ * LiYong Sep 23,2003 Port from EZX ++ * Jin Lihong(w20076) Jan 02,2004,LIBdd66088 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * lin weiqiang Jun.08,2004,LIBee14656 record noise bug fix. ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/poll.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-audio.h" ++#include "ezx-common.h" ++ ++ ++static DECLARE_MUTEX(cotulla_assp_mono_mutex); ++ ++EXPORT_SYMBOL(set_pcap_telephone_codec); ++EXPORT_SYMBOL(set_pcap_input_path); ++EXPORT_SYMBOL(set_pcap_output_path); ++ ++static int assp_mono_init(void); ++static void assp_mono_shutdown(void); ++ ++void set_pcap_telephone_codec(int port) ++{ ++ unsigned long ssp_pcap_register_val; ++ SSP_PCAP_BIT_STATUS phoneClkBit; ++ /* set pcap register, telephone codec */ ++ /* (1) set pcap audio power V2_EN_2(OR WITH V2_EN) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ ++ /* disable PCAP stereo DAC */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_ST_DAC_REGISTER, 0); ++ /* (2) set codec sample rate(FS_8K_16K=0) */ ++ /* CDC_CLK(000=13MHZ) bitclk output(SMB=0) audio IO1(DIG_AUD_IN=1) */ ++ ssp_pcap_register_val = PCAP_CDC_CLK_IN_13M0; ++ phoneClkBit = SSP_PCAP_get_bit_from_PCAP(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_CODEC_REGISTER, ssp_pcap_register_val); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB); /* master */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); /* 8K sample rate */ ++/* ++ if( SSP_PCAP_BIT_ONE == phoneClkBit) ++ { ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ } ++ else ++ { ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ } ++*/ ++ if(port) ++ { ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DIG_AUD_IN); /* DAI1 */ ++ } ++ else ++ { ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_DIG_AUD_IN); /* DAI0 */ ++ } ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDIHPF); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDOHPF); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_INV); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_INV); ++ ++ /*(3) reset digital filter(DF_RESET=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_ADITH); ++ /* (4) enable pcap clk(CDC_CLK_EN=1),enable CODEC(CDC_EN=1) */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ mdelay(1); /* specified enable time */ ++} ++ ++ ++void set_pcap_output_path(void) ++{ ++ int ret; ++ ++ /* enable output_path */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ST_DAC_SW); /* close stereo switch */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); /* close PGA_INR into PGA */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CDC_SW); /* open telephone switch */ ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN); /* enable right PGA */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); /* disable left PGA */ ++ ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); /* right+left output */ ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_output_path = %d\n", codec_output_path); ++ printk(EZXOSS_DEBUG "codec_output_base = %d\n", codec_output_base); ++#endif ++ ret = (*mixer_open_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(codec_output_base|codec_output_path); ++} ++ ++ ++void set_pcap_input_path(void) ++{ ++ unsigned long ssp_pcap_register_val; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_input_path=%d\n", codec_input_path); ++#endif ++ ++ (*mixer_open_input_path[codec_input_path])(); ++ set_input_gain_hw_reg(); ++ ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val); ++ printk(EZXOSS_DEBUG "pcap register 26 = 0x%lx\n", ssp_pcap_register_val); ++#endif ++} ++ ++ ++/*initialize hardware, assp controller and pcap register*/ ++static int assp_mono_init(void) ++{ ++ unsigned long flags; ++ unsigned long ssp_pcap_register_val; ++ unsigned int audiostatus; ++ unsigned long timeout; ++ ++/* ++#ifdef CONFIG_ARCH_EZX_E680 ++ if( audioonflag & FM_DEVICE ){ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 open dsp16 EBUSY because 0x%X device is using the sound hardware.\n",audioonflag ); ++#endif ++ return -EBUSY; ++ } ++#endif ++*/ ++ ++ audioonflag |= DSP16_DEVICE; ++ ++ down(&cotulla_assp_mono_mutex); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "setup assp controller register \n"); ++#endif ++ local_irq_save(flags); ++ CKEN |= CKEN4_ASSP; /* need enable cken4 */ ++ ++ set_GPIO_mode(GPIO_SYNC_IN_ASSP_MD); ++ set_GPIO_mode(GPIO_SDATA_OUT_ASSP_MD); ++ set_GPIO_mode(GPIO_BITCLK_IN_ASSP_MD); ++ set_GPIO_mode(GPIO_SDATA_IN_ASSP_MD); ++ ++ /* setup assp port */ ++ ASSCR0 = ASSCR0_FRF_PSP | ASSCR0_DSS_16bit; /* psp mode, 16bit */ ++ ASSCR1 = ASSCR1_TTE | ASSCR1_EBCEI | ASSCR1_SCLKDIR | ASSCR1_SFRMDIR | ASSCR1_RFTH_14 | ASSCR1_TFTH_4; ++ ASSPSP = ASSPSP_SFRMWDTH_1 | ASSPSP_STRTDLY_1 | ASSPSP_SFRMP_HIGH | ASSPSP_SCMODE; ++ ASSCR1 |= ASSCR1_RSRE | ASSCR1_TSRE; /* enable transmit and receive dma request */ ++ ASSCR0 |= ASSCR0_SSE; /* enable assp controller */ ++ local_irq_restore(flags); ++ ++#ifdef EZX_OSS_DEBUG ++ audiostatus = ASSCR0; ++ printk(EZXOSS_DEBUG "ASSCR0 = 0x%lx\n", audiostatus); ++ audiostatus = ASSCR1; ++ printk(EZXOSS_DEBUG "ASSCR1 = 0x%lx\n", audiostatus); ++ audiostatus = ASSPSP; ++ printk(EZXOSS_DEBUG "ASSPSP = 0x%lx\n", audiostatus); ++#endif ++ ++ mute_output_to_avoid_pcap_noise(); ++ ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++ if( MONODEVOPENED == DSP16_DEVICE ) ++ pcap_use_ap_13m_clock(); ++ ++/* not in phone call, PCAP telephone */ ++ if((audioonflag & PHONE_DEVICE)==0){ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "setup pcap audio register\n"); ++#endif ++ set_pcap_telephone_codec(1); ++ set_pcap_output_path(); ++ set_pcap_input_path(); ++ } ++ else{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "there is phone call\n"); ++#endif ++ /* set pcap register, stereo DAC */ ++ //SSP_PCAP_read_data_from_PCAP(SSP_PCAP_ADJ_ST_DAC_REGISTER, &ssp_pcap_register_val); ++ //ssp_pcap_register_val |= PCAP_ST_SAMPLE_RATE_8K | PCAP_ST_BCLK_SLOT_4 | PCAP_ST_CLK_PLL_CLK_IN_BITCLK | PCAP_DIGITAL_AUDIO_INTERFACE_NETWORK; //NETWORK mode ++ //SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_ST_DAC_REGISTER, ssp_pcap_register_val); ++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_8K); ++ SSP_PCAP_BCLK_set(PCAP_ST_BCLK_SLOT_4); ++ SSP_PCAP_STCLK_set(PCAP_ST_CLK_PLL_CLK_IN_FSYNC); ++ SSP_PCAP_DIG_AUD_FS_set(PCAP_DIGITAL_AUDIO_INTERFACE_NETWORK); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_INV); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_FS_INV); ++ ++ /* (3) reset digital filter(DF_RESET_ST_DAC=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_DF_RESET_ST_DAC); ++ ++ /* (4)set bitclk output(SMB_ST_DAC=0), audio IO=part1(DIG_AUD_IN_ST_DAC=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_SMB_ST_DAC); /* input, slave mode */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_DIG_AUD_IN_ST_DAC); ++ ++ /* (5) enable pcap clk(ST_CLK_EN=1),enable dac(ST_DAC_EN=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN); ++ mdelay(1); /* specified enable time according spec */ ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ST_DAC_SW); /* close stereo switch */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); /* enable left PGA */ ++ } ++ ++ undo_mute_output_to_avoid_pcap_noise(); ++ ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(0x0d,&ssp_pcap_register_val); ++ printk(EZXOSS_DEBUG "pcap register 13 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0c,&ssp_pcap_register_val); ++ printk(EZXOSS_DEBUG "pcap register 12 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0b,&ssp_pcap_register_val); ++ printk(EZXOSS_DEBUG "pcap register 11 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val); ++ printk(EZXOSS_DEBUG "pcap register 26 = 0x%lx\n", ssp_pcap_register_val); ++#endif ++ timeout = 0; ++ /* check if ssp is ready for slave operation */ ++ while(((audiostatus = ASSSR) & ASSSR_CSS) !=0){ ++ if((timeout++) > 10000000) ++ goto err; ++ } ++ ++ up(&cotulla_assp_mono_mutex); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " complete all hardware init \n"); ++#endif ++ return 0; ++ ++err: ++ up(&cotulla_assp_mono_mutex); ++ printk(EZXOSS_DEBUG "audio panic2: ssp don't ready for slave operation!!! "); ++ return -ENODEV; ++} ++ ++ ++static void assp_mono_shutdown(void) ++{ ++ unsigned long ssp_pcap_register_val; ++ ++ down(&cotulla_assp_mono_mutex); ++ ++ /* clear ASSP port */ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close assp port\n"); ++#endif ++ ASSCR0 = 0; ++ ASSCR1 = 0; ++ ASSPSP = 0; ++ CKEN &= ~CKEN4_ASSP; ++ ++ set_GPIO_mode(GPIO_ASSP_SCLK3 | GPIO_IN); /* Assp Frame sync */ ++ set_GPIO_mode(GPIO_ASSP_TXD3 | GPIO_IN); ++ set_GPIO_mode(GPIO_ASSP_RXD3 | GPIO_IN); /* ASSP BitCLK */ ++ set_GPIO_mode(GPIO_ASSP_SFRM3 | GPIO_IN); /* ASsp RX */ ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close pcap register\n"); ++#endif ++ ++ mute_output_to_avoid_pcap_noise(); /* mute hw noise and save power */ ++ ++ if( MONODEVOPENED == DSP16_DEVICE ) ++ pcap_use_bp_13m_clock(); ++ ++ if((audioonflag & PHONE_DEVICE) == 0){ ++ /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER,SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ /* close pcap input path */ ++ if(micinflag) ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_TX_AUD_AMPS_REGISTER,SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2); ++ else ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_TX_AUD_AMPS_REGISTER, 0); ++ /* disable PCAP mono codec */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_DIG_AUD_IN); /* DAI0 */ ++ /* set fsync, tx, bitclk are tri-stated */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CD_TS); ++ } ++ else{ ++ /* disable PCAP stereo DAC */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_SMB_ST_DAC); ++ } ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ e680_boomer_path_mono_lineout(); /* mute hw noise and save power for e680 */ ++#endif ++ ++ audioonflag &= ~DSP16_DEVICE; ++ ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(0x0d,&ssp_pcap_register_val); ++ printk("pcap register 13 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0c,&ssp_pcap_register_val); ++ printk("pcap register 12 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0b,&ssp_pcap_register_val); ++ printk("pcap register 11 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val); ++ printk("pcap register 26 = 0x%lx\n", ssp_pcap_register_val); ++#endif ++ up(&cotulla_assp_mono_mutex); ++} ++ ++ ++/* ++ * ASSP codec ioctls ++ */ ++static int codec_adc_rate = PHONE_CODEC_DEFAULT_RATE; /* default 8k sample rate */ ++static int codec_dac_rate = PHONE_CODEC_DEFAULT_RATE; /* default 8k sample rate */ ++ ++static int assp_mono_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret; ++ long val; ++ int audiostatus, timeout; ++ ++ switch(cmd) { ++ case SNDCTL_DSP_STEREO: ++#ifdef EZX_OSS_DEBUG ++ printk(" check if support stereo\n"); ++#endif ++ ret = get_user(val, (int *) arg); ++ if (ret) ++ return ret; ++ ++ if(val) ++ ret = -EINVAL; /* not support stereo */ ++ else ++ ret = 1; ++ return put_user(ret, (int *) arg); ++ ++ case SNDCTL_DSP_CHANNELS: ++ case SOUND_PCM_READ_CHANNELS: ++#ifdef EZX_OSS_DEBUG ++ printk(" check if 2 channels \n"); ++#endif ++ return put_user(1, (long *) arg); ++ ++ case SNDCTL_DSP_SPEED: ++#ifdef EZX_OSS_DEBUG ++ printk(" set sample frequency \n"); ++#endif ++ ret = get_user(val, (long *) arg); ++ if (ret) ++ return ret; ++ ++ down(&cotulla_assp_mono_mutex); ++ ASSCR0 &= ~ASSCR0_SSE; ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ switch(val) ++ { ++ case PHONE_CODEC_16K_RATE: ++ ret= SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); ++ codec_adc_rate = val; ++ codec_dac_rate = val; ++ break; ++ case PHONE_CODEC_DEFAULT_RATE: ++ ret = SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); ++ codec_adc_rate = val; ++ codec_dac_rate = val; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ /* reset digital filter(DF_RESET=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ ++ ASSCR0 |= ASSCR0_SSE; /* enable assp controller */ ++ timeout = 0; ++ /* check if ssp is ready for slave operation */ ++ while(((audiostatus = ASSSR) & ASSSR_CSS) !=0) ++ { ++ if((timeout++) > 10000000) ++ { ++ printk("audio panic3: can't be slave mode!!!"); ++ ret = -ENODEV; ++ break; ++ } ++ } ++#ifdef EZX_OSS_DEBUG ++ printk("AD sample freq = %d\n", codec_adc_rate); ++ printk("DA sample freq = %d\n", codec_dac_rate); ++#endif ++ up(&cotulla_assp_mono_mutex); ++ return put_user(codec_adc_rate, (long *) arg); ++ ++ case SOUND_PCM_READ_RATE: ++ if (file->f_mode & FMODE_WRITE) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk("read DA sample freq\n"); ++#endif ++ val = codec_dac_rate; ++ } ++ if (file->f_mode & FMODE_READ) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk("read AD sample freq\n"); ++#endif ++ val = codec_adc_rate; ++ } ++ return put_user(val, (long *) arg); ++ ++ case SNDCTL_DSP_SETFMT: ++ case SNDCTL_DSP_GETFMTS: ++ /* SUPPORT little endian signed 16 */ ++#ifdef EZX_OSS_DEBUG ++ printk("data format is AFMT_S16_LEd\n"); ++#endif ++ return put_user(AFMT_S16_LE, (long *) arg); ++ ++ default: ++ return mixer_ioctl(inode, file, cmd, arg); ++ } ++ return 0; ++} ++ ++ ++/* ++ * Audio stuff ++ */ ++static audio_stream_t assp_mono_audio_out = { ++ name: "assp mono audio out", ++ dcmd: DCMD_TXASSDRM, ++ drcmr: &DRCMRTXASSDR, /* ASSP dma map register */ ++ dev_addr: __PREG(ASSDR), ++}; ++ ++static audio_stream_t assp_mono_audio_in = { ++ name: "assp mono audio in", ++ dcmd: DCMD_RXASSDR, ++ drcmr: &DRCMRRXASSDR, /* ASSP dma map register */ ++ dev_addr: __PREG(ASSDR), ++}; ++ ++static audio_state_t assp_mono_audio_state = { ++ output_stream: &assp_mono_audio_out, ++ input_stream: &assp_mono_audio_in, ++ client_ioctl: assp_mono_ioctl, ++ hw_init: assp_mono_init, ++ hw_shutdown: assp_mono_shutdown, ++ sem: __MUTEX_INITIALIZER(assp_mono_audio_state.sem), ++}; ++ ++static int assp_mono_audio_open(struct inode *inode, struct file *file) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk("assp mono audio open \n"); ++#endif ++ ++ return cotulla_audio_attach(inode, file, &assp_mono_audio_state); ++} ++ ++/* ++ * Missing fields of this structure will be patched with the call ++ * to cotulla_audio_attach(). ++ */ ++ ++static struct file_operations assp_mono_audio_fops = { ++ open: assp_mono_audio_open, ++ owner: THIS_MODULE ++}; ++ ++static int __init cotulla_assp_mono_init(void) ++{ ++ assp_mono_audio_state.dev_dsp = register_sound_dsp16(&assp_mono_audio_fops, -1); ++ ++#ifdef EZX_OSS_DEBUG ++ printk("/dev/dsp16 init ok\n"); ++#endif ++ return 0; ++} ++ ++static void __exit cotulla_assp_mono_exit(void) ++{ ++ unregister_sound_dsp16(assp_mono_audio_state.dev_dsp); ++#ifdef EZX_OSS_DEBUG ++ printk("/dev/dsp16 exit ok\n"); ++#endif ++} ++ ++module_init(cotulla_assp_mono_init); ++module_exit(cotulla_assp_mono_exit); ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-assps.c linux-2.6.16.5-exz/sound/oss/ezx-assps.c +--- linux-2.6.16.5/sound/oss/ezx-assps.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-assps.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,1168 @@ ++/*
++ * linux/drivers/sound/ezx-assps.c
++ *
++ *
++ * Description: assp interface for the ezx platform
++ *
++ *
++ * Copyright: BJDC motorola.
++ *
++ * This program 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.
++ *
++ *
++ * History:
++ * zhouqiong Jun 20,2002 created
++ * zhouqiong Sep 19,2002 according code review meeting minutes.
++ * zhouqiong Oct 30,2002 according new requirement for VA.ASSP interface split to
++ * /dev/dsp (support stereo playback) and /dev/dsp16 (support
++ * mono playback and record) this file is for stereo playback.
++ * zhouqiong Nov 05,2002 according code review meeting minutes.
++ * zhouqiong Jan 13,2003 (1) add audio panic return value
++ * (2) modify sample frequency to standard
++ * zhouqiong Mar 03,2003 (1) open headset interrupt
++ * (2) change gain when headset is in
++ * (3) add ioctl to get headset status
++ * zhouqiong Apr 17,2003 (1) according codec_dac_rate init pcap
++ * zhouqiong Apr 18,2003 (1) change output gain according output path
++ * zhouqiong Apr 24,2003 (1) no switch when headset insert and remove
++ * zhouqiong May 21,2003 (1) modify loudspk gain max 0db, for audio-shaping
++ * LiYong Sep 23,2003 (1)Port from EZX; (2)Modify the ASSP port inital
++ * Jin Lihong(w20076) Jan 02,2004,Libdd66088 (1) Port from UDC e680 kernel of jem vob.
++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h
++ * header file,and redefine DEBUG to EZX_OSS_DEBUG
++ * (3) reorganize file header
++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Make the e680 louder speaker work.
++ * Jia Tong(w19836) Feb 04,2004,LIBdd67717 haptics feature added
++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs
++ * Jia Tong(w19836) Feb 23,2004,LIBdd79841 haptics GPIO initialization change
++ * Li Yong(w19946) Feb 26,2004 LIBdd80614 Add DAI test
++ * Add control to switch PCAP CODEC mode from master to slave mode
++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix
++ * Jia Tong(w19836) Mar 17,2004,LIBdd87621 GPIO change for haptics filter & boomer mute while setting haptics.
++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface
++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app
++ * Li Yong(w19946) Apr.23.2004.LIBee02702 Add EMU Carkit
++ * Li Yong(w19946) May.23.2004.LIBee12065 Add the EMU audio test
++ * lin weiqiang Jun.08,2004,LIBee14656 record noise bug fix.
++ * Jin Lihong(w20076) Jun.22,2004,LIBee24284 mixer power save ++ * Jin Lihong(w20076) Aug.11,2004,LIBff01482 audio pcap LOW_POWER bit initialize ++ * ++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/pci.h>
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/poll.h>
++#include <linux/pm.h> ++#include <linux/sound.h>
++#include <linux/soundcard.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++#include <asm/dma.h>
++
++#include "ezx-audio.h"
++#include "ezx-common.h"
++
++
++static DECLARE_MUTEX(cotulla_assp_mutex);
++
++static int codec_dac_rate = STEREO_CODEC_44K_RATE; /* default 44k sample rate */
++static struct timer_list audio_timer,mic_timer;
++ ++#ifdef CONFIG_PM ++static struct pm_dev *mixer_hw_pm_dev; ++#endif
++ ++ ++EXPORT_SYMBOL(headjack_change_interrupt_routine);
++EXPORT_SYMBOL(mic_change_interrupt_routine);
++EXPORT_SYMBOL(mixer_ioctl);
++
++static int assp_init(void);
++static void assp_shutdown(void);
++static void change_input_output(void);
++static void open_mic_interrupt(void);
++
++void Set_EMU_Mux_Switch(int mode);
++void EIHF_Mute(int Flag);
++
++static int EMU_AUD_test_flag = 0;
++
++static struct timer_list EMU_timer;
++
++/*initialize hardware, assp controller and pcap register*/
++static int assp_init(void)
++{
++ unsigned long flags;
++ unsigned long ssp_pcap_register_val;
++ unsigned long audiostatus;
++ unsigned long timeout;
++ int ret;
++
++ down(&cotulla_assp_mutex);
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "setup assp controller register \n");
++#endif
++ local_irq_save(flags);
++ CKEN |= CKEN4_ASSP; /* need enable cken4 */
++
++ set_GPIO_mode(GPIO_SYNC_IN_ASSP_MD); /* Assp Frame sync */
++ set_GPIO_mode(GPIO_SDATA_OUT_ASSP_MD); /* Assp TX */
++ set_GPIO_mode(GPIO_BITCLK_IN_ASSP_MD); /* ASSP BitCLK */
++ set_GPIO_mode(GPIO_SDATA_IN_ASSP_MD); /* ASsp RX */
++
++ /* setup assp port */
++ ASSCR0 = ASSCR0_FRF_PSP | ASSCR0_EDSS | ASSCR0_DSS_16bit; /* PSP mode, 32bit */
++ ASSCR1 = ASSCR1_EBCEI | ASSCR1_SCLKDIR | ASSCR1_SFRMDIR | ASSCR1_TFTH_4;
++ ASSPSP = ASSPSP_SFRMWDTH_16 | ASSPSP_SCMODE;
++ ASSCR1 |= ASSCR1_TSRE; /* enable transmit dma request */
++ ASSCR0 |= ASSCR0_SSE; /* enable assp controller */
++ local_irq_restore(flags);
++
++#ifdef EZX_OSS_DEBUG
++ audiostatus = ASSCR0;
++ printk(EZXOSS_DEBUG "ASSCR0 = 0x%lx\n", audiostatus);
++ audiostatus = ASSCR1;
++ printk(EZXOSS_DEBUG "ASSCR1 = 0x%lx\n", audiostatus);
++ audiostatus = ASSPSP;
++ printk(EZXOSS_DEBUG "ASSPSP = 0x%lx\n", audiostatus);
++#endif
++
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "setup pcap audio register\n");
++#endif
++ ++ mute_output_to_avoid_pcap_noise(); ++ poweron_mixer(DSP_DEVICE);
++
++ /* (1) set bitclk(BCK=3, two_time_slot) pll clock(ST_CLK=0, 13M) NORMAL mode(DIG_AUD_FS =00) */
++ ssp_pcap_register_val = PCAP_ST_BCLK_SLOT_2 | PCAP_ST_CLK_PLL_CLK_IN_13M0 | PCAP_DIGITAL_AUDIO_INTERFACE_NORMAL; //NORMAL mode
++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_ST_DAC_REGISTER, ssp_pcap_register_val);
++ /* here dsp device must use AP 13Mhz clock */
++ pcap_use_ap_13m_clock();
++
++ /* set stereo sample rate */
++ switch(codec_dac_rate)
++ {
++ case STEREO_CODEC_48K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_48K);
++ break;
++
++ case STEREO_CODEC_44K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_44K);
++ break;
++
++ case STEREO_CODEC_32K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_32K);
++ break;
++
++ case STEREO_CODEC_24K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_24K);
++ break;
++
++ case STEREO_CODEC_22K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_22K);
++ break;
++
++ case STEREO_CODEC_16K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_16K);
++ break;
++
++ case STEREO_CODEC_12K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_12K);
++ break;
++
++ case STEREO_CODEC_11K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_11K);
++ break;
++
++ case STEREO_CODEC_8K_RATE:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_8K);
++ break;
++ default:
++ SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_44K);
++ break;
++ }
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "codec_dac_rate=%d\n", codec_dac_rate);
++#endif
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_INV);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_FS_INV);
++
++ /* (3) reset digital filter(DF_RESET_ST_DAC=1) */
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_DF_RESET_ST_DAC);
++
++ /* (4)set bitclk output(SMB_ST_DAC=0), audio IO=part1(DIG_AUD_IN_ST_DAC=1) */
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_SMB_ST_DAC);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_DIG_AUD_IN_ST_DAC);
++
++ /* (5) enable pcap clk(ST_CLK_EN=1),enable dac(ST_DAC_EN=1) */
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN);
++ mdelay(1); /* specified enable time according spec */
++ ++#ifdef CONFIG_ARCH_EZX_A780 ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_output_path=%d\n", codec_output_path);
++ printk(EZXOSS_DEBUG "codec_output_base=%d\n", codec_output_base);
++#endif
++ ret = (*mixer_open_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(codec_output_base|codec_output_path); ++#endif ++ ++ undo_mute_output_to_avoid_pcap_noise(); ++
++#ifdef EZX_OSS_DEBUG
++ SSP_PCAP_read_data_from_PCAP(0x0d,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 13 = 0x%lx\n", ssp_pcap_register_val);
++ SSP_PCAP_read_data_from_PCAP(0x0c,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 12 = 0x%lx\n", ssp_pcap_register_val);
++ SSP_PCAP_read_data_from_PCAP(0x0b,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 11 = 0x%lx\n", ssp_pcap_register_val);
++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 26 = 0x%lx\n", ssp_pcap_register_val);
++#endif
++ timeout = 0;
++ /* check if ssp is ready for slave operation */
++ while(((audiostatus = ASSSR) & ASSSR_CSS) !=0)
{ ++ if((timeout++) > 10000000)
++ goto err;
++ }
++
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " complete all hardware init \n");
++#endif
++ up(&cotulla_assp_mutex);
++
++ return 0;
++err:
++ up(&cotulla_assp_mutex);
++ printk(EZXOSS_DEBUG "audio panic: ssp don't ready for slave operation!!! ");
++ return -ENODEV;
++}
++
++
++static void assp_shutdown(void)
++{
++ down(&cotulla_assp_mutex);
++
++ /* clear ASSP port */
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "close assp port\n");
++#endif
++ ASSCR0 = 0;
++ ASSCR1 = 0;
++ ASSPSP = 0;
++ CKEN &= ~CKEN4_ASSP;
++
++ set_GPIO_mode(GPIO_ASSP_SCLK3 | GPIO_IN); /* Assp Frame sync */
++ set_GPIO_mode(GPIO_ASSP_TXD3 | GPIO_IN);
++ set_GPIO_mode(GPIO_ASSP_RXD3 | GPIO_IN); /* ASSP BitCLK */
++ set_GPIO_mode(GPIO_ASSP_SFRM3 | GPIO_IN); /* ASsp RX */
++ ++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "close pcap register\n");
++#endif
++ ++ shutdown_mixer(DSP_DEVICE);
++
++ /* disable PCAP stereo DAC */
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_SMB_ST_DAC);
++ pcap_use_bp_13m_clock();
++ ++ up(&cotulla_assp_mutex);
++} ++
++
++/*
++ * for stereo headset and mono headset insert, it will take A1I interrupt
++ * in A1I interrupt handler, open MB_ON2 to check if mic connect
++ */
++void headjack_change_interrupt_routine(int ch, void *dev_id, struct pt_regs *regs)
++{
++ int bdelay = 20;
++
++ del_timer(&audio_timer);
++ init_timer(&audio_timer);
++ audio_timer.function = change_input_output;
++ audio_timer.expires = (jiffies + bdelay);
++ add_timer(&audio_timer);
++}
++
++
++static void open_mic_interrupt(void)
++{
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "Open mic interrupt\n");
++#endif
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ISR_MB2I );
++ udelay(10);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_MSR_MB2M);
++}
++
++
++void Set_EMU_Mux_Switch(int mode)
++{
++ set_GPIO_mode(GPIO_EMU_MUX1 | GPIO_OUT);
++ set_GPIO_mode(GPIO_EMU_MUX2 | GPIO_OUT);
++
++ switch(mode)
++ {
++ case DEFAULT_USB_MODE:
++ clr_GPIO(GPIO_EMU_MUX1);
++ clr_GPIO(GPIO_EMU_MUX2); //default mode
++ break;
++
++ case MONO_AUDIO_MODE:
++ set_GPIO(GPIO_EMU_MUX1);
++ clr_GPIO(GPIO_EMU_MUX2); //Mono audio mode
++ break;
++
++ case SETERO_AUDIO_MODE:
++ set_GPIO(GPIO_EMU_MUX1);
++ set_GPIO(GPIO_EMU_MUX2); //Setero audio mode
++ break;
++
++ default:
++ break;
++ }
++
++ printk("::set EMU Mux GPIO.\n");
++}
++
++void EIHF_Mute(int Flag)
++{
++
++ set_GPIO_mode(GPIO_SNP_INT_CTL | GPIO_OUT);
++ if(EMU_AUD_test_flag) //At the audio EMU test mode
++ {
++ clr_GPIO(GPIO_SNP_INT_CTL);
++ return;
++ }
++
++ if(!Flag)
++ {
++ clr_GPIO(GPIO_SNP_INT_CTL);
++ }
++ else
++ {
++ set_GPIO(GPIO_SNP_INT_CTL); // high is active
++ }
++
++}
++
++void Switch_Audio_To_USB()
++{
++ set_GPIO_mode(GPIO_SNP_INT_IN | GPIO_IN);
++
++ while(1) //If the EMU ID short to GND
++ {
++ if(!(GPLR(GPIO_SNP_INT_IN) & GPIO_bit(GPIO_SNP_INT_IN)))
++ break;
++ }
++ EIHF_Mute(EIHF_MUTE);
++ Set_EMU_Mux_Switch(DEFAULT_USB_MODE); // Switch the MUX to USB mode
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP); // Disable the PCAP loopback
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232ENB);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PS);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_VUSB_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PU); //Pull up the D+
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ISR_USB4VI);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_MSR_USB4VM);
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ISR_USB1VI);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_MSR_USB1VM);
++
++ EMU_AUD_test_flag = 0; // Restore the default value
++}
++
++void Switch_USB_To_Audio()
++{
++ EMU_AUD_test_flag = 0xff; // Enter the EMU audio test mode
++ set_GPIO_mode(GPIO_SNP_INT_IN | GPIO_IN);
++
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_MSR_USB4VM);
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_MSR_USB1VM);
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_RS232ENB);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PS);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_BUSCTRL_VUSB_EN);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_BUSCTRL_USB_PU);
++
++
++ del_timer(&EMU_timer); //Start one timer
++ init_timer(&EMU_timer);
++ EMU_timer.function = Switch_Audio_To_USB;
++ EMU_timer.expires = (jiffies+500);
++ add_timer(&EMU_timer);
++}
++
++
++
++static void change_input_output(void)
++{
++ unsigned long ssp_pcap_bit_status;
++
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "enter headjack change interrupt routine \n");
++#endif
++ /* read pcap register to check if headjack is in */
++ ssp_pcap_bit_status = SSP_PCAP_get_bit_from_PCAP(SSP_PCAP_ADJ_BIT_PSTAT_A1SNS);
++ if(ssp_pcap_bit_status) /* headset is in */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "headset insert\n");
++#endif
++ headset_in_handler(0, NULL, NULL);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2);
++ micinflag = 1;
++ del_timer(&mic_timer);
++ init_timer(&mic_timer);
++ mic_timer.function = open_mic_interrupt;
++ mic_timer.expires = (jiffies+100);
++ add_timer(&mic_timer);
++ }
++ else /* headset is out */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "headset remove\n");
++#endif
++ headset_out_handler(0, NULL, NULL);
++ micinflag = 0;
++ del_timer(&mic_timer);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ISR_MB2I);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_MSR_MB2M);
++ }
++}
++
++
++void mic_change_interrupt_routine(int ch, void *dev_id, struct pt_regs *regs)
++{
++ int ssp_pcap_bit_status;
++
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "enter mic change interrupt routine \n");
++#endif
++
++ /* read pcap register to check if headjack is in */
++ ssp_pcap_bit_status = SSP_PCAP_get_bit_from_PCAP(SSP_PCAP_ADJ_BIT_PSTAT_A1SNS);
++ if( ssp_pcap_bit_status ) /* headjack is in */
++ {
++ answer_button_handler(0, NULL, NULL);
++ }
++}
++
++
++/*
++ * Audio Mixer stuff
++ */
++int mixer_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int ret;
++ int i,j;
++ long val;
++ unsigned long ssp_pcap_register_val;
++
++ switch(cmd)
++ {
++#ifdef MAKE_FTR_HAPTICS ++ case SOUND_MIXER_WRITE_HAPTICS_ON:
++ Set_Haptics_GPIO();
++ break;
++ case SOUND_MIXER_WRITE_HAPTICS_OFF:
++ Clear_Haptics_GPIO();
++ break;
++ case SOUND_MIXER_READ_HAPTICS_FIL: ++ if( (GPDR(GPIO_FLT_SEL_BUL) & GPIO_bit(GPIO_FLT_SEL_BUL))==0 ) ++ val = 0; ++ else ++ val = 1; ++ return put_user(val, (long *)arg); ++#endif
++ ++ case SOUND_MIXER_READ_IGAIN:
++ val = codec_input_gain;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " read input gain=%d\n", val);
++#endif
++ return put_user(val, (long *)arg);
++
++ case SOUND_MIXER_WRITE_IGAIN:
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++
++ if( (val<EZX_OSS_MIN_LOGICAL_GAIN) || (val>EZX_OSS_MAX_LOGICAL_GAIN) )
++ ret = -EINVAL;
++ else{
++ codec_input_gain = val;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " write input gain=%d\n", codec_input_gain);
++#endif
++ set_input_gain_hw_reg();
++ }
++
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_READ_OGAIN:
++ /* read pcap ogain register */
++ val = codec_output_gain;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " read output gain=%d\n", val);
++#endif
++ return put_user(val, (long *)arg);
++
++ case SOUND_MIXER_WRITE_VOLUME:
++ case SOUND_MIXER_WRITE_OGAIN:
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " write output gain=%d\n", val);
++#endif
++
++ if((val >= EZX_OSS_MIN_LOGICAL_GAIN)&&(val <=EZX_OSS_MAX_LOGICAL_GAIN))
++ {
++ codec_output_gain = val;
++ /* write pcap ogain register */
++ set_output_gain_hw_reg();
++ }
++ else
++ {
++ ret = -EINVAL;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "value is invalid\n");
++#endif
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_READ_RECSRC:
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " read input path\n");
++#endif
++ /* read pcap input status, 0-extmic, 1-A5, 2-A3 */
++ val = codec_input_path;
++ return put_user(val, (long *)arg);
++
++ case SOUND_MIXER_WRITE_RECSRC:
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " force write input path=%d\n", val);
++#endif
++ /* close old input path */
++ (*mixer_close_input_path[codec_input_path])();
++ /* open input path */
++ if( (val>INPUT_PATH_MAX) || (val<INPUT_PATH_MIN) )
++ ret = -EINVAL;
++ else
++ (*mixer_open_input_path[val])();
++ ++ if( audioonflag == 0 ) ++ mixer_not_in_use(); /* for power save */ ++ ++#ifdef EZX_OSS_DEBUG
++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 26 = 0x%lx\n", ssp_pcap_register_val);
++#endif
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_READ_OUTSRC:
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " read output path\n");
++#endif
++ val = codec_output_path | codec_output_base;
++ return put_user(val, (long *)arg);
++
++ case SOUND_MIXER_WRITE_OUTSRC:
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "force write output path=0x%03X\n", val);
++#endif
++ /* close old output path */
++ (*mixer_close_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])();
++
++ /* set pcap output register */
++ if( (GET_OUTPUT_BASE(val)>OUTPUT_BASE_MAX) || (GET_OUTPUT_PATH(val)>OUTPUT_PATH_MAX) )
++ ret = -EINVAL;
++ else
++ ret = (*mixer_open_output_path[OUTPUT_BASE_TYPE(GET_OUTPUT_BASE(val))][GET_OUTPUT_PATH(val)])(val);
++
++ if( audioonflag == 0 ) ++ mixer_not_in_use(); /* for power save */ ++ ++#ifdef EZX_OSS_DEBUG
++ SSP_PCAP_read_data_from_PCAP(0x0c,&ssp_pcap_register_val);
++ printk(EZXOSS_DEBUG "pcap register 12 = 0x%lx\n", ssp_pcap_register_val);
++#endif
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_MUTE: /* mute output path */
++ /* 0-unmute, 1-mute */
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++ if(val == 1) /* if mute */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " mute PGA\n");
++#endif
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN);
++ }
++ else if(val == 0) /* unmute */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "unmute PGA\n");
++#endif
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN);
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_INPUTMUTE: /* mute input path for DAI test */
++ /* 0-unmute, 1-mute */
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++ if(val == 1) /* if mute */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " mute input\n");
++#endif
++ (*mixer_close_input_path[codec_input_path])();
++ }
++ else if(val == 0) /* unmute */
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "unmute input\n");
++#endif
++ (*mixer_open_input_path[codec_input_path])();
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_LOOPBACK: /* set loopback mode for DAI test */
++ /* 0-unloopback, 1-loopback */
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++ if(val == 1)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "loopback\n");
++#endif
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP);
++
++
++ }
++ else if(val ==0)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "unloopback\n");
++#endif
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP);
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_AUDOHPF: /* set audio output High Pass filter for test command */
++ /* 0-disable filter, 1-enable filter */
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++ if(val == 1)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "enable audio output High Pass filter\n");
++#endif
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDOHPF);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET);
++
++ }
++ else if(val ==0)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "disable audio output High Pass filter\n");
++#endif
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDOHPF);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET);
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_AUDIHPF: /* set audio input High Pass filter for test command */
++ /* 0-disable filter, 1-enable filter */
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++ if(val == 1)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk("enable audio input High Pass filter\n");
++#endif
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDIHPF);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET);
++
++ }
++ else if(val ==0)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk("disable audio input High Pass filter\n");
++#endif
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDIHPF);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET);
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_CODEC_SLAVE:
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET);
++ return put_user(ret, (int *) arg);
++ case SOUND_MIXER_READ_HEADSET_STATUS: /* read if headset is in */
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "read headset status, jiffies=%d\n", jiffies);
++#endif
++
++ j=0;
++ for(i=0;i<3;i++)
++ {
++ val = SSP_PCAP_get_bit_from_PCAP(SSP_PCAP_ADJ_BIT_PSTAT_A1SNS);
++ if(val)
++ j++;
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(50*HZ/1000);
++ }
++ if(j>=2)
++ {
++ ret = STEREO_HEADSET;
++ micinflag=1;
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_MSR_MB2M);
++ }
++ else
++ {
++ ret = NO_HEADSET;
++ micinflag=0;
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_MSR_MB2M);
++ }
++ return put_user(ret, (long *)arg);
++
++ case SOUND_MIXER_WRITE_EIHF_MUX:
++ ret = get_user(val, (long *) arg);
++ if(ret)
++ return ret;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " \n user space is writing MUX status =%d\n", val);
++#endif
++ switch(val)
++ {
++ case DEFAULT_USB_MODE:
++ Set_EMU_Mux_Switch(DEFAULT_USB_MODE);
++ break;
++ case MONO_AUDIO_MODE:
++ Set_EMU_Mux_Switch(MONO_AUDIO_MODE);
++ break;
++ case SETERO_AUDIO_MODE:
++ Set_EMU_Mux_Switch(SETERO_AUDIO_MODE);
++ break;
++ default:
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SOUND_MIXER_WRITE_EIHF_MUTE:
++ ret = get_user(val, (long *) arg);
++ if(ret)
++ return ret;
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " \n user space is writing MUTE status =%d\n", val);
++#endif
++ if(val)
++ EIHF_Mute(EIHF_UNMUTE);
++ else
++ EIHF_Mute(EIHF_MUTE);
++
++ return put_user(ret, (int *) arg);
++ case SOUND_MIXER_WRITE_EMU_TEST:
++ ret = get_user(val, (long *) arg);
++ if(ret)
++ return ret;
++ Switch_USB_To_Audio();
++ return put_user(ret, (int *) arg);
++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ case SOUND_MIXER_READ_3D_STATUS: ++ val = get_boomer_3d_status(); ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " read e680 3d status =%d\n", val); ++#endif ++ return put_user(val, (long *)arg); ++ ++ case SOUND_MIXER_WRITE_3D_STATUS: ++ ret = get_user(val, (long *) arg); ++ if(ret) ++ return ret; ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " user space is writing 3d status =%d\n", val); ++#endif ++ ++ if( (val<LOUDERSPEAKER_ON_HEADSET_ON_3D) || (val>LOUDERSPEAKER_OFF_HEADSET_OFF_3D) ) ++ ret = -EINVAL; ++ else ++ set_boomer_3d_status((boomer_3d_status)val); ++ ++ return put_user(ret, (int *) arg); ++#endif ++ ++#ifdef CONFIG_ARCH_EZX_A780 ++ case SOUND_MIXER_WRITE_HW_ATTENU: ++ ret = get_user(val, (long *) arg); ++ if(ret) ++ return ret; ++ ++ if(val == HW_ATTENUATION_USED){ ++ use_hw_noise_attenuate(); ++ ret = HW_ATTENUATION_USED; ++ } ++ else if(val == HW_ATTENUATION_BYPASSED){ ++ bypass_hw_noise_attenuate(); ++ ret = HW_ATTENUATION_BYPASSED; ++ } ++ else ++ ret = -EINVAL; ++ ++ return put_user(ret, (int *) arg); ++#endif ++ ++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static struct file_operations mixer_fops = {
++ ioctl: mixer_ioctl,
++ owner: THIS_MODULE
++};
++
++/*
++ * ASSP codec ioctls
++ */
++
++static int assp_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int ret;
++ long val;
++ int audiostatus, timeout;
++
++ switch(cmd) {
++ case SNDCTL_DSP_STEREO:
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " check if support stereo\n");
++#endif
++ ret = get_user(val, (int *) arg);
++ if (ret)
++ return ret;
++ if(file->f_mode & FMODE_WRITE)
++ {
++ if(val) /* write only support stereo mode */
++ ret = 1;
++ else /* not support mono mode */
++ ret = -EINVAL;
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(ret, (int *) arg);
++
++ case SNDCTL_DSP_CHANNELS:
++ case SOUND_PCM_READ_CHANNELS:
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " check if 2 channels \n");
++#endif
++ if(file->f_mode & FMODE_WRITE)
++ {
++ return put_user(2, (long *) arg);
++ }
++ else
++ {
++ ret = -EINVAL;
++ return put_user(ret, (long *) arg);
++ }
++
++ case SNDCTL_DSP_SPEED:
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG " set sample frequency \n");
++#endif
++ ret = get_user(val, (long *) arg);
++ if (ret)
++ return ret;
++
++ if(file->f_mode & FMODE_WRITE)
++ {
++ down(&cotulla_assp_mutex);
++ ASSCR0 &= ~ASSCR0_SSE;
++
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN);
++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN);
++ switch(val)
++ {
++ case STEREO_CODEC_48K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_48K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_44K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_44K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_32K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_32K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_24K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_24K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_22K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_22K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_16K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_16K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_12K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_12K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_11K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_11K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++
++ case STEREO_CODEC_8K_RATE:
++ ret = SSP_PCAP_CDC_SR_set(PCAP_ST_SAMPLE_RATE_8K);
++ /* set pcap dac sample rate */
++ codec_dac_rate = val;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ /* reset digital filter(DF_RESET_ST_DAC=1) */
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_DF_RESET_ST_DAC);
++
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_CLK_EN);
++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_EN);
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "DA sample freq = %d\n", codec_dac_rate);
++#endif
++ ASSCR0 |= ASSCR0_SSE; /* enable assp controller */
++ timeout = 0;
++ /* check if ssp is ready for slave operation */
++ while(((audiostatus = ASSSR) & ASSSR_CSS) !=0)
++ {
++ if((timeout++) > 10000000)
++ {
++ printk(EZXOSS_DEBUG "audio panic: can't be slave mode!!!");
++ ret = -ENODEV;
++ break;
++ }
++ }
++ up(&cotulla_assp_mutex);
++ }
++ else
++ {
++ ret = -EINVAL;
++ }
++ return put_user(codec_dac_rate, (long *) arg);
++
++ case SOUND_PCM_READ_RATE:
++ if (file->f_mode & FMODE_WRITE)
++ {
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "read DA sample freq\n");
++#endif
++ val = codec_dac_rate;
++ }
++ else
++ {
++ val = -EINVAL;
++ }
++ return put_user(val, (long *) arg);
++
++ case SNDCTL_DSP_SETFMT:
++ case SNDCTL_DSP_GETFMTS:
++ /* SUPPORT little endian signed 16 */
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "data format is AFMT_S16_LEd\n");
++#endif
++ return put_user(AFMT_S16_LE, (long *) arg);
++
++ default:
++ return mixer_ioctl(inode, file, cmd, arg);
++ }
++ return 0;
++}
++
++
++/*
++ * Audio stuff
++ */
++static audio_stream_t assp_audio_out = {
++ name: "assp audio out",
++ dcmd: DCMD_TXASSDR,
++ drcmr: &DRCMRTXASSDR, /* ASSP dma map register */
++ dev_addr: __PREG(ASSDR),
++};
++
++
++static audio_stream_t assp_audio_in = {
++ name: "assp audio in",
++ dcmd: DCMD_RXASSDR,
++ drcmr: &DRCMRRXASSDR, /* ASSP dma map register */
++ dev_addr: __PREG(ASSDR),
++};
++
++
++static audio_state_t assp_audio_state = {
++ output_stream: &assp_audio_out,
++ input_stream: &assp_audio_in,
++ client_ioctl: assp_ioctl,
++ hw_init: assp_init,
++ hw_shutdown: assp_shutdown,
++ sem: __MUTEX_INITIALIZER(assp_audio_state.sem),
++};
++
++
++static int assp_audio_open(struct inode *inode, struct file *file)
++{
++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "assp audio open \n");
++#endif
++
++ return cotulla_audio_attach(inode, file, &assp_audio_state);
++}
++
++
++/*
++ * Missing fields of this structure will be patched with the call
++ * to cotulla_audio_attach().
++ */
++static struct file_operations assp_audio_fops = {
++ open: assp_audio_open,
++ owner: THIS_MODULE
++};
++
++
++static int mixer_dev_id;
++
++static int __init cotulla_assp_init(void)
++{
++ assp_audio_state.dev_dsp = register_sound_dsp(&assp_audio_fops, -1);
++ mixer_dev_id = register_sound_mixer(&mixer_fops, -1);
++
++ set_GPIO_mode(GPIO_ASSP_SCLK3 | GPIO_IN); /* Assp Frame sync */
++ set_GPIO_mode(GPIO_ASSP_TXD3 | GPIO_IN);
++ set_GPIO_mode(GPIO_ASSP_RXD3 | GPIO_IN); /* ASSP BitCLK */
++ set_GPIO_mode(GPIO_ASSP_SFRM3 | GPIO_IN); /* ASsp RX */
++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ Clear_Haptics_GPIO(); ++ e680_boomer_init(); ++#endif ++ ++#ifdef CONFIG_PM ++ mixer_hw_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mixer_hw_pm_callback); ++#endif ++ ++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "cotulla-assp-init ok\n");
++#endif
++ return 0;
++}
++
++
++static void __exit cotulla_assp_exit(void)
++{
++ unregister_sound_dsp(assp_audio_state.dev_dsp);
++ unregister_sound_mixer(mixer_dev_id);
++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ e680_boomer_shutdown(); ++#endif ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ ++#ifdef CONFIG_PM ++ pm_unregister(mixer_hw_pm_dev); ++#endif ++ ++#ifdef EZX_OSS_DEBUG
++ printk(EZXOSS_DEBUG "cotulla-assp-exit ok\n");
++#endif
++}
++
++
++module_init(cotulla_assp_init);
++module_exit(cotulla_assp_exit);
++
++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-audio.c linux-2.6.16.5-exz/sound/oss/ezx-audio.c +--- linux-2.6.16.5/sound/oss/ezx-audio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-audio.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,1122 @@ ++/* ++ * linux/drivers/sound/ezx-audio.c ++ * ++ * ++ * Description: audio interface for ezx ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhouqiong Jun 20,2002 created ++ * LiYong Sep 23,2003 (1)Port from EZX ++ * Jin Lihong(w20076) Jan 02,2004,Libdd66088 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_AUDIO_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * Jin Lihong(w20076) Jun.15,2004,LIBee21625 boomer's power management ++ * Jin Lihong(w20076) Aug.11,2004,LIBff01482 DMA channel release bug fix ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-common.h" ++#include "ezx-audio.h" ++ ++ ++#define AUDIO_NBFRAGS_DEFAULT 8 ++#define AUDIO_FRAGSIZE_DEFAULT 8192 ++ ++#define MAX_DMA_SIZE 4096 ++#define DMA_DESC_SIZE sizeof(pxa_dma_desc) ++ ++#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref) ++ ++ ++/* ++ * This function frees all buffers ++ */ ++static void audio_clear_buf(audio_stream_t *s) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ int frag; ++ ++ if (!s->buffers) ++ return; ++ ++ /* Ensure DMA isn't running */ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("ensure dma isn't running\n"); ++#endif ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&s->stop_wq, &wait); ++ DCSR(s->dma_ch) = DCSR_STOPIRQEN; ++ schedule(); ++ remove_wait_queue(&s->stop_wq, &wait); ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("free dma buffers\n"); ++#endif ++ /* free DMA buffers */ ++ for (frag = 0; frag < s->nbfrags; frag++) { ++ audio_buf_t *b = &s->buffers[frag]; ++ if (!b->master) ++ continue; ++ consistent_free(b->data, b->master, b->dma_desc->dsadr); ++ } ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("free descriptor buffers\n"); ++#endif ++ /* free descriptor ring */ ++ if (s->buffers->dma_desc) ++ consistent_free(s->buffers->dma_desc, ++ s->nbfrags * s->descs_per_frag * DMA_DESC_SIZE, ++ s->dma_desc_phys); ++ ++ /* free buffer structure array */ ++ kfree(s->buffers); ++ s->buffers = NULL; ++} ++ ++/* ++ * This function allocates the DMA descriptor array and buffer data space ++ * according to the current number of fragments and fragment size. ++ */ ++static int audio_setup_buf(audio_stream_t *s) ++{ ++ pxa_dma_desc *dma_desc; ++ dma_addr_t dma_desc_phys; ++ int nb_desc, frag, i, buf_size = 0; ++ char *dma_buf = NULL; ++ dma_addr_t dma_buf_phys = 0; ++ ++ if (s->buffers) ++ return -EBUSY; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("audio setup buffer \n"); ++#endif ++ /* Our buffer structure array */ ++ s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL); ++ if (!s->buffers) ++ goto err; ++ memzero(s->buffers, sizeof(audio_buf_t) * s->nbfrags); ++ ++ /* ++ * Our DMA descriptor array: ++ * for Each fragment we have one checkpoint descriptor plus one ++ * descriptor per MAX_DMA_SIZE byte data blocks. ++ */ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("malloc descriptor memory\n"); ++#endif ++ nb_desc = (1 + (s->fragsize + MAX_DMA_SIZE - 1)/MAX_DMA_SIZE) * s->nbfrags; ++ dma_desc = consistent_alloc(GFP_KERNEL, ++ nb_desc * DMA_DESC_SIZE, ++ &dma_desc_phys); ++ if (!dma_desc) ++ goto err; ++ s->descs_per_frag = nb_desc / s->nbfrags; ++ s->buffers->dma_desc = dma_desc; ++ s->dma_desc_phys = dma_desc_phys; ++ for (i = 0; i < nb_desc - 1; i++) ++ dma_desc[i].ddadr = dma_desc_phys + (i + 1) * DMA_DESC_SIZE; ++ dma_desc[i].ddadr = dma_desc_phys; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("malloc dma memory\n"); ++#endif ++ /* Our actual DMA buffers */ ++ for (frag = 0; frag < s->nbfrags; frag++) { ++ audio_buf_t *b = &s->buffers[frag]; ++ ++ /* ++ * Let's allocate non-cached memory for DMA buffers. ++ * We try to allocate all memory at once. ++ * If this fails (a common reason is memory fragmentation), ++ * then we'll try allocating smaller buffers. ++ */ ++ if (!buf_size) { ++ buf_size = (s->nbfrags - frag) * s->fragsize; ++ do { ++ dma_buf = consistent_alloc(GFP_KERNEL, ++ buf_size, ++ &dma_buf_phys); ++ if (!dma_buf) ++ buf_size -= s->fragsize; ++ } while (!dma_buf && buf_size); ++ if (!dma_buf) ++ goto err; ++ b->master = buf_size; ++ memzero(dma_buf, buf_size); ++ } ++ ++ /* ++ * Set up our checkpoint descriptor. Since the count ++ * is always zero, we'll abuse the dsadr and dtadr fields ++ * just in case this one is picked up by the hardware ++ * while processing SOUND_DSP_GETPTR. ++ */ ++ dma_desc->dsadr = dma_buf_phys; ++ dma_desc->dtadr = dma_buf_phys; ++ dma_desc->dcmd = DCMD_ENDIRQEN; ++ if (s->output && !s->mapped) ++ dma_desc->ddadr |= DDADR_STOP; ++ b->dma_desc = dma_desc++; ++ ++ /* set up the actual data descriptors */ ++ for (i = 0; (i * MAX_DMA_SIZE) < s->fragsize; i++) { ++ dma_desc[i].dsadr = (s->output) ? ++ (dma_buf_phys + i*MAX_DMA_SIZE) : s->dev_addr; ++ dma_desc[i].dtadr = (s->output) ? ++ s->dev_addr : (dma_buf_phys + i*MAX_DMA_SIZE); ++ dma_desc[i].dcmd = s->dcmd | ++ ((s->fragsize < MAX_DMA_SIZE) ? ++ s->fragsize : MAX_DMA_SIZE); ++ } ++ dma_desc += i; ++ ++ /* handle buffer pointers */ ++ b->data = dma_buf; ++ dma_buf += s->fragsize; ++ dma_buf_phys += s->fragsize; ++ buf_size -= s->fragsize; ++ } ++ ++ s->usr_frag = s->dma_frag = 0; ++ s->bytecount = 0; ++ s->getptrCount = 0; ++ s->fragcount = 0; ++ sema_init(&s->sem, (s->output) ? s->nbfrags : 0); ++ return 0; ++ ++err: ++ printk("cotulla-audio: unable to allocate audio memory\n "); ++ audio_clear_buf(s); ++ return -ENOMEM; ++} ++ ++/* ++ * Our DMA interrupt handler ++ */ ++static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs) ++{ ++ audio_stream_t *s = dev_id; ++ u_int dcsr; ++ ++ dcsr = DCSR(ch); ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("dcsr=0x%lx\n", dcsr); ++#endif ++ DCSR(ch) = dcsr & ~DCSR_STOPIRQEN; ++ ++ if (!s->buffers) { ++ printk("SSP DMA: wow... received IRQ for channel %d but no buffer exists\n", ch); ++ return; ++ } ++ ++ if (dcsr & DCSR_BUSERR) ++ printk("SSP DMA: bus error interrupt on channel %d\n", ch); ++ ++ if (dcsr & DCSR_ENDINTR) ++ { ++ u_long cur_dma_desc; ++ u_int cur_dma_frag; ++ ++ /* ++ * Find out which DMA desc is current. Note that DDADR ++ * points to the next desc, not the current one. ++ */ ++ cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE; ++ /* ++ * Let the compiler nicely optimize constant divisors into ++ * multiplications for the common cases which is much faster. ++ * Common cases: x = 1 + (1 << y) for y = [0..3] ++ */ ++ switch (s->descs_per_frag) { ++ case 2: cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break; ++ case 3: cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break; ++ case 5: cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break; ++ case 9: cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break; ++ default: cur_dma_frag = ++ cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE); ++ } ++ ++ /* Account for possible wrap back of cur_dma_desc above */ ++ if (cur_dma_frag >= s->nbfrags) ++ cur_dma_frag = s->nbfrags - 1; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("cur_dma_frag=0x%lx\n", cur_dma_frag); ++ printk("s->dma_frag=0x%lx\n", s->dma_frag); ++#endif ++ while (s->dma_frag != cur_dma_frag) { ++ if (!s->mapped) { ++ /* ++ * This fragment is done - set the checkpoint ++ * descriptor to STOP until it is gets ++ * processed by the read or write function. ++ */ ++ s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP; ++ up(&s->sem); ++ } ++ if (++s->dma_frag >= s->nbfrags) ++ s->dma_frag = 0; ++ ++ /* Accounting */ ++ s->bytecount += s->fragsize; ++ s->fragcount++; ++ } ++ ++ /* ... and for polling processes */ ++ wake_up(&s->frag_wq); ++ } ++ ++ if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE)) ++ wake_up(&s->stop_wq); ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("audio dma irq complete\n"); ++#endif ++} ++ ++/* ++ * Validate and sets up buffer fragments, etc. ++ */ ++static int audio_set_fragments(audio_stream_t *s, int val) ++{ ++ if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN) ++ return -EBUSY; ++ if (s->buffers) ++ audio_clear_buf(s); ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("audio set fragments\n"); ++#endif ++ s->nbfrags = (val >> 16) & 0x7FFF; ++ val &= 0xffff; ++ if (val < 5) ++ val = 5; ++ if (val > 15) ++ val = 15; ++ s->fragsize = 1 << val; ++ if (s->nbfrags < 2) ++ s->nbfrags = 2; ++ if (s->nbfrags * s->fragsize > 256 * 1024) ++ s->nbfrags = 256 * 1024 / s->fragsize; ++ if (audio_setup_buf(s)) ++ return -ENOMEM; ++ return val|(s->nbfrags << 16); ++} ++ ++ ++/* ++ * The fops functions ++ */ ++ ++static int audio_write(struct file *file, const char *buffer, ++ size_t count, loff_t *ppos) ++{ ++ const char *buffer0 = buffer; ++ audio_state_t *state = (audio_state_t *)file->private_data; ++ audio_stream_t *s = state->output_stream; ++ int chunksize, ret = 0; ++ unsigned int audiostatus; ++ ++ if (ppos != &file->f_pos) ++ return -ESPIPE; ++ if (s->mapped) ++ return -ENXIO; ++ if (!s->buffers && audio_setup_buf(s)) ++ return -ENOMEM; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio write \n"); ++ printk("buffer0=0x%lx\n", buffer0); ++ printk("count=%d\n", count); ++#endif ++ while (count > 0) { ++ audio_buf_t *b = &s->buffers[s->usr_frag]; ++ ++ /* Grab a fragment */ ++ if (file->f_flags & O_NONBLOCK) { ++ ret = -EAGAIN; ++ if (down_trylock(&s->sem)) ++ break; ++ } else { ++ ret = -ERESTARTSYS; ++ if (down_interruptible(&s->sem)) ++ break; ++ } ++ ++ /* Feed the current buffer */ ++ chunksize = s->fragsize - b->offset; ++ if (chunksize > count) ++ chunksize = count; ++ if (copy_from_user(b->data + b->offset, buffer, chunksize)) { ++ up(&s->sem); ++ return -EFAULT; ++ } ++ b->offset += chunksize; ++ buffer += chunksize; ++ ++ count -= chunksize; ++ if (b->offset < s->fragsize) { ++ up(&s->sem); ++ break; ++ } ++ ++ /* ++ * Activate DMA on current buffer. ++ * We unlock this fragment's checkpoint descriptor and ++ * kick DMA if it is idle. Using checkpoint descriptors ++ * allows for control operations without the need for ++ * stopping the DMA channel if it is already running. ++ */ ++ b->offset = 0; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enable dma run\n"); ++#endif ++ b->dma_desc->ddadr &= ~DDADR_STOP; ++ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { ++ DDADR(s->dma_ch) = b->dma_desc->ddadr; ++ DCSR(s->dma_ch) = DCSR_RUN; ++ } ++ ++ /* move the index to the next fragment */ ++ if (++s->usr_frag >= s->nbfrags) ++ s->usr_frag = 0; ++ } ++ ++ if ((buffer - buffer0)) ++ ret = buffer - buffer0; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("write bytes=0x%x \n", ret); ++#endif ++ return ret; ++} ++ ++ ++static int audio_read(struct file *file, char *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *buffer0 = buffer; ++ audio_state_t *state = file->private_data; ++ audio_stream_t *s = state->input_stream; ++ int chunksize, ret = 0; ++ ++ if (ppos != &file->f_pos) ++ return -ESPIPE; ++ if (s->mapped) ++ return -ENXIO; ++ if (!s->buffers && audio_setup_buf(s)) ++ return -ENOMEM; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio read \n"); ++ printk("buffer0=0x%lx\n", buffer0); ++ printk("count=%d\n", count); ++#endif ++ while (count > 0) { ++ audio_buf_t *b = &s->buffers[s->usr_frag]; ++ ++ /* prime DMA */ ++ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { ++ DDADR(s->dma_ch) = ++ s->buffers[s->dma_frag].dma_desc->ddadr; ++ DCSR(s->dma_ch) = DCSR_RUN; ++ } ++ ++ /* Wait for a buffer to become full */ ++ if (file->f_flags & O_NONBLOCK) { ++ ret = -EAGAIN; ++ if (down_trylock(&s->sem)) ++ break; ++ } else { ++ ret = -ERESTARTSYS; ++ if (down_interruptible(&s->sem)) ++ break; ++ } ++ ++ /* Grab data from current buffer */ ++ chunksize = s->fragsize - b->offset; ++ if (chunksize > count) ++ chunksize = count; ++ if (copy_to_user(buffer, b->data + b->offset, chunksize)) { ++ up(&s->sem); ++ return -EFAULT; ++ } ++ b->offset += chunksize; ++ buffer += chunksize; ++ count -= chunksize; ++ if (b->offset < s->fragsize) { ++ up(&s->sem); ++ break; ++ } ++ ++ /* ++ * Make this buffer available for DMA again. ++ * We unlock this fragment's checkpoint descriptor and ++ * kick DMA if it is idle. Using checkpoint descriptors ++ * allows for control operations without the need for ++ * stopping the DMA channel if it is already running. ++ */ ++ b->offset = 0; ++ b->dma_desc->ddadr &= ~DDADR_STOP; ++ ++ /* move the index to the next fragment */ ++ if (++s->usr_frag >= s->nbfrags) ++ s->usr_frag = 0; ++ } ++ ++ if ((buffer - buffer0)) ++ ret = buffer - buffer0; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("read bytes=0x%x \n", ret); ++#endif ++ return ret; ++} ++ ++ ++static int audio_sync(struct file *file) ++{ ++ audio_state_t *state = file->private_data; ++ audio_stream_t *s = state->output_stream; ++ audio_buf_t *b; ++ pxa_dma_desc *final_desc; ++ u_long dcmd_save = 0; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) ++ return 0; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio sync \n"); ++#endif ++ /* ++ * Send current buffer if it contains data. Be sure to send ++ * a full sample count. ++ */ ++ final_desc = NULL; ++ b = &s->buffers[s->usr_frag]; ++ if (b->offset &= ~3) ++ { ++ final_desc = &b->dma_desc[1 + b->offset/MAX_DMA_SIZE]; ++ b->offset &= (MAX_DMA_SIZE-1); ++ dcmd_save = final_desc->dcmd; ++ final_desc->dcmd = b->offset | s->dcmd | DCMD_ENDIRQEN; ++ final_desc->ddadr |= DDADR_STOP; ++ b->offset = 0; ++ b->dma_desc->ddadr &= ~DDADR_STOP; ++ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { ++ DDADR(s->dma_ch) = b->dma_desc->ddadr; ++ DCSR(s->dma_ch) = DCSR_RUN; ++ } ++ } ++ ++ /* Wait for DMA to complete. */ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&s->frag_wq, &wait); ++ while ((DCSR(s->dma_ch) & DCSR_RUN) && !signal_pending(current)) { ++ schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ } ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&s->frag_wq, &wait); ++ ++ /* Restore the descriptor chain. */ ++ if (final_desc) { ++ final_desc->dcmd = dcmd_save; ++ final_desc->ddadr &= ~DDADR_STOP; ++ b->dma_desc->ddadr |= DDADR_STOP; ++ } ++ return 0; ++} ++ ++ ++static unsigned int audio_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ audio_state_t *state = file->private_data; ++ audio_stream_t *is = state->input_stream; ++ audio_stream_t *os = state->output_stream; ++ unsigned int mask = 0; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio poll \n"); ++#endif ++ if (file->f_mode & FMODE_READ) { ++ /* Start audio input if not already active */ ++ if (!is->buffers && audio_setup_buf(is)) ++ return -ENOMEM; ++ if (DCSR(is->dma_ch) & DCSR_STOPSTATE) { ++ DDADR(is->dma_ch) = ++ is->buffers[is->dma_frag].dma_desc->ddadr; ++ DCSR(is->dma_ch) = DCSR_RUN; ++ } ++ poll_wait(file, &is->frag_wq, wait); ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ if (!os->buffers && audio_setup_buf(os)) ++ return -ENOMEM; ++ poll_wait(file, &os->frag_wq, wait); ++ } ++ ++ if (file->f_mode & FMODE_READ) ++ if (( is->mapped && (is->bytecount != is->getptrCount)) || ++ (!is->mapped && atomic_read(&is->sem.count) > 0)) ++ mask |= POLLIN | POLLRDNORM; ++ ++ if (file->f_mode & FMODE_WRITE) ++ if (( os->mapped && (os->bytecount != os->getptrCount)) || ++ (!os->mapped && atomic_read(&os->sem.count) > 0)) ++ mask |= POLLOUT | POLLWRNORM; ++ ++ return mask; ++} ++ ++ ++static int audio_ioctl( struct inode *inode, struct file *file, ++ uint cmd, ulong arg) ++{ ++ audio_state_t *state = file->private_data; ++ audio_stream_t *os = state->output_stream; ++ audio_stream_t *is = state->input_stream; ++ long val; ++ ++ switch (cmd) { ++ case OSS_GETVERSION: ++ return put_user(SOUND_VERSION, (int *)arg); ++ ++ case SNDCTL_DSP_GETBLKSIZE: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get block size\n"); ++#endif ++ if (file->f_mode & FMODE_WRITE) ++ return put_user(os->fragsize, (int *)arg); ++ else ++ return put_user(is->fragsize, (int *)arg); ++ ++ case SNDCTL_DSP_GETCAPS: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get audio capability \n"); ++#endif ++ val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; ++ if (is && os) ++ val |= DSP_CAP_DUPLEX; ++ return put_user(val, (int *)arg); ++ ++ case SNDCTL_DSP_SETFRAGMENT: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("set fragment no\n"); ++#endif ++ if (get_user(val, (long *) arg)) ++ return -EFAULT; ++ ++ if (file->f_mode & FMODE_READ) ++ { ++ int ret = audio_set_fragments(is, val); ++ if (ret < 0) ++ return ret; ++ ret = put_user(ret, (int *)arg); ++ if (ret) ++ return ret; ++ } ++ if (file->f_mode & FMODE_WRITE) ++ { ++ int ret = audio_set_fragments(os, val); ++ if (ret < 0) ++ return ret; ++ ret = put_user(ret, (int *)arg); ++ if (ret) ++ return ret; ++ } ++ return 0; ++ ++ case SNDCTL_DSP_SYNC: ++ return audio_sync(file); ++ ++ case SNDCTL_DSP_SETDUPLEX: ++ return 0; ++ ++ case SNDCTL_DSP_POST: ++ return 0; ++ ++ case SNDCTL_DSP_GETTRIGGER: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get trigger\n"); ++#endif ++ val = 0; ++ if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN) ++ val |= PCM_ENABLE_INPUT; ++ if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN) ++ val |= PCM_ENABLE_OUTPUT; ++ return put_user(val, (int *)arg); ++ ++ case SNDCTL_DSP_SETTRIGGER: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("set trigger\n"); ++#endif ++ if (get_user(val, (int *)arg)) ++ return -EFAULT; ++ if (file->f_mode & FMODE_READ) ++ { ++ if (val & PCM_ENABLE_INPUT) ++ { ++ if (!is->buffers && audio_setup_buf(is)) ++ return -ENOMEM; ++ if (!(DCSR(is->dma_ch) & DCSR_RUN)) ++ { ++ audio_buf_t *b = &is->buffers[is->dma_frag]; ++ DDADR(is->dma_ch) = b->dma_desc->ddadr; ++ DCSR(is->dma_ch) = DCSR_RUN; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("start read dma channel\n"); ++#endif ++ } ++ } else{ ++ DCSR(is->dma_ch) = 0; ++ } ++ } ++ if (file->f_mode & FMODE_WRITE) ++ { ++ if (val & PCM_ENABLE_OUTPUT) ++ { ++ if (!os->buffers && audio_setup_buf(os)) ++ return -ENOMEM; ++ if (!(DCSR(os->dma_ch) & DCSR_RUN)) { ++ audio_buf_t *b = &os->buffers[os->dma_frag]; ++ DDADR(os->dma_ch) = b->dma_desc->ddadr; ++ DCSR(os->dma_ch) = DCSR_RUN; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("start write dma channel\n"); ++#endif ++ } ++ } else{ ++ DCSR(os->dma_ch) = 0; ++ } ++ } ++ return 0; ++ ++ case SNDCTL_DSP_GETOSPACE: ++ case SNDCTL_DSP_GETISPACE: ++ { ++ audio_buf_info inf = { 0, }; ++ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get input and output space size\n"); ++#endif ++ if ((s == is && !(file->f_mode & FMODE_READ)) || ++ (s == os && !(file->f_mode & FMODE_WRITE))) ++ return -EINVAL; ++ if (!s->buffers && audio_setup_buf(s)) ++ return -ENOMEM; ++ ++ inf.bytes = atomic_read(&s->sem.count) * s->fragsize; ++ inf.bytes -= s->buffers[s->usr_frag].offset; ++ inf.fragments = inf.bytes / s->fragsize; ++ inf.fragsize = s->fragsize; ++ inf.fragstotal = s->nbfrags; ++ ++ return copy_to_user((void *)arg, &inf, sizeof(inf)); ++ } ++ ++ case SNDCTL_DSP_GETOPTR: ++ case SNDCTL_DSP_GETIPTR: ++ { ++ count_info inf = { 0, }; ++ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; ++ dma_addr_t ptr; ++ int bytecount, offset, flags; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get input and output pointer\n"); ++#endif ++ if ((s == is && !(file->f_mode & FMODE_READ)) || ++ (s == os && !(file->f_mode & FMODE_WRITE))) ++ return -EINVAL; ++ ++ if (DCSR(s->dma_ch) & DCSR_RUN) ++ { ++ audio_buf_t *b; ++ save_flags_cli(flags); ++ ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch); ++ b = &s->buffers[s->dma_frag]; ++ offset = ptr - b->dma_desc->dsadr; ++ if (offset >= s->fragsize) ++ offset = s->fragsize - 4; ++ } else ++ { ++ save_flags(flags); ++ offset = 0; ++ } ++ inf.ptr = s->dma_frag * s->fragsize + offset; ++ bytecount = s->bytecount + offset; ++ s->getptrCount = s->bytecount; /* so poll can tell if it changes */ ++ inf.blocks = s->fragcount; ++ s->fragcount = 0; ++ restore_flags(flags); ++ if (bytecount < 0) ++ bytecount = 0; ++ inf.bytes = bytecount; ++ return copy_to_user((void *)arg, &inf, sizeof(inf)); ++ } ++ ++ case SNDCTL_DSP_NONBLOCK: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("set device none block mode\n"); ++#endif ++ file->f_flags |= O_NONBLOCK; ++ return 0; ++ ++ case SNDCTL_DSP_GETODELAY: ++ { ++ int count = 0, offset; ++ int i; ++ int flags; ++ audio_buf_t *b; ++ dma_addr_t ptr; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("get output delay\n "); ++#endif ++ if(!(file->f_mode & FMODE_WRITE)) ++ return -EINVAL; ++ if(!os->buffers && audio_setup_buf(os)) ++ return -ENOMEM; ++ ++ save_flags_cli(flags); ++ for(i = 0; i < os->nbfrags; i++){ ++ /* if contain data */ ++ if(atomic_read(&os->sem.count) <= 0){ ++ count += os->fragsize; ++ } ++ } ++ if (DCSR(os->dma_ch) & DCSR_RUN) ++ { ++ ptr = DSADR(os->dma_ch); ++ b = &os->buffers[os->dma_frag]; ++ offset = ptr - b->dma_desc->dsadr; ++ if (offset >= os->fragsize) ++ offset = os->fragsize - 4; ++ } else ++ { ++ offset = 0; ++ } ++ count -= offset; ++ restore_flags(flags); ++ return put_user(count,(int *)arg); ++ } ++ ++ case SNDCTL_DSP_RESET: ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("reset audio data buffer\n"); ++#endif ++ if (file->f_mode & FMODE_WRITE) ++ audio_clear_buf(os); ++ if (file->f_mode & FMODE_READ) ++ audio_clear_buf(is); ++ return 0; ++ ++ default: ++ return state->client_ioctl(inode, file, cmd, arg); ++ } ++ ++ return 0; ++} ++ ++ ++static int audio_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ audio_state_t *state = file->private_data; ++ audio_stream_t *s; ++ unsigned long size, vma_addr; ++ int i, ret; ++ ++ if (vma->vm_pgoff != 0) ++ return -EINVAL; ++ ++ if (vma->vm_flags & VM_WRITE) { ++ if (!state->wr_ref) ++ return -EINVAL; ++ s = state->output_stream; ++ } else if (vma->vm_flags & VM_READ) { ++ if (!state->rd_ref) ++ return -EINVAL; ++ s = state->input_stream; ++ } else return -EINVAL; ++ ++ if (s->mapped) ++ return -EINVAL; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio mmap \n"); ++#endif ++ size = vma->vm_end - vma->vm_start; ++ if (size != s->fragsize * s->nbfrags) ++ return -EINVAL; ++ if (!s->buffers && audio_setup_buf(s)) ++ return -ENOMEM; ++ ++ vma_addr = vma->vm_start; ++ for (i = 0; i < s->nbfrags; i++) { ++ audio_buf_t *buf = &s->buffers[i]; ++ if (!buf->master) ++ continue; ++ ret = remap_page_range(vma_addr, buf->dma_desc->dsadr, ++ buf->master, vma->vm_page_prot); ++ if (ret) ++ return ret; ++ vma_addr += buf->master; ++ } ++ for (i = 0; i < s->nbfrags; i++) ++ s->buffers[i].dma_desc->ddadr &= ~DDADR_STOP; ++ ++ s->mapped = 1; ++ return 0; ++} ++ ++ ++static int audio_release(struct inode *inode, struct file *file) ++{ ++ audio_state_t *state = file->private_data; ++ audio_stream_t *is = state->input_stream; ++ audio_stream_t *os = state->output_stream; ++ ++ down(&state->sem); ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("enter audio release \n"); ++#endif ++ if (file->f_mode & FMODE_READ) ++ { ++ audio_clear_buf(state->input_stream); ++ *is->drcmr = 0; ++ pxa_free_dma(is->dma_ch); ++ state->rd_ref = 0; ++ } ++ ++ if (file->f_mode & FMODE_WRITE) ++ { ++ audio_sync(file); ++ audio_clear_buf(state->output_stream); ++ *os->drcmr = 0; ++ pxa_free_dma(os->dma_ch); ++ state->wr_ref = 0; ++ } ++ ++ if (!AUDIO_ACTIVE(state)) { ++ if (state->hw_shutdown) ++ state->hw_shutdown(); ++#ifdef CONFIG_PM ++ pm_unregister(state->pm_dev); ++#endif ++ } ++ ++ up(&state->sem); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int audio_dma_sleep(audio_stream_t *s) ++{ ++ dmach_t channel; ++ ++ channel = s->dma_ch; ++ DCSR(channel)=DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("DINT=0x%lx\n", DINT); ++ printk("DCSR(%d)=0x%lx\n", channel, DCSR(channel)); ++ printk("s->dcmd=0x%lx\n", s->dcmd); ++ printk("*s->drcmr=0x%lx\n", *s->drcmr); ++ printk("DDADR(%d)=0x%lx\n", channel, DDADR(channel)); ++#endif ++ return 0; ++} ++ ++static int audio_dma_wakeup(audio_stream_t *s) ++{ ++ dmach_t channel; ++ ++ channel = s->dma_ch; ++ DCSR(channel)=DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; ++ *s->drcmr = s->dma_ch | DRCMR_MAPVLD; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("DINT=0x%lx\n", DINT); ++ printk("DCSR(%d)=0x%lx\n", channel, DCSR(channel)); ++ printk("s->dcmd=0x%lx\n", s->dcmd); ++ printk("*s->drcmr=0x%lx\n", *s->drcmr); ++ printk("DDADR(%d)=0x%lx\n", channel, DDADR(channel)); ++#endif ++ return 0; ++} ++ ++static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ audio_state_t *state = (audio_state_t *)pm_dev->data; ++ ++ switch (req) { ++ case PM_SUSPEND: /* enter D1-D3 */ ++ if (state->output_stream) ++ audio_dma_sleep(state->output_stream); ++ if (state->input_stream) ++ audio_dma_sleep(state->input_stream); ++ if (AUDIO_ACTIVE(state) && state->hw_shutdown) ++ state->hw_shutdown(); ++ break; ++ case PM_RESUME: /* enter D0 */ ++ if (AUDIO_ACTIVE(state) && state->hw_init) ++ state->hw_init(); ++ if (state->output_stream) ++ audio_dma_wakeup(state->output_stream); ++ if (state->input_stream) ++ audio_dma_wakeup(state->input_stream); ++ break; ++ } ++ return 0; ++} ++#endif ++ ++ ++int cotulla_audio_attach(struct inode *inode, struct file *file, ++ audio_state_t *state) ++{ ++ audio_stream_t *is = state->input_stream; ++ audio_stream_t *os = state->output_stream; ++ int err; ++ ++ down(&state->sem); ++ ++ /* access control */ ++ err = -ENODEV; ++ if ((file->f_mode & FMODE_WRITE) && !os) ++ goto out; ++ if ((file->f_mode & FMODE_READ) && !is) ++ goto out; ++ ++ err = -EBUSY; ++ if ((file->f_mode & FMODE_WRITE) && state->wr_ref) ++ goto out; ++ if ((file->f_mode & FMODE_READ) && state->rd_ref) ++ goto out; ++ ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("request dma channels \n"); ++#endif ++ /* request DMA channels */ ++ if (file->f_mode & FMODE_WRITE) ++ { ++ err = pxa_request_dma(os->name, DMA_PRIO_LOW, audio_dma_irq, os); ++ if (err < 0) ++ goto out; ++ os->dma_ch = err; ++ } ++ ++ if (file->f_mode & FMODE_READ) ++ { ++ err = pxa_request_dma(is->name, DMA_PRIO_LOW, audio_dma_irq, is); ++ if (err < 0){ ++ if(file->f_mode & FMODE_WRITE){ ++ *os->drcmr = 0; ++ pxa_free_dma(os->dma_ch); ++ } ++ goto out; ++ } ++ is->dma_ch = err; ++ } ++ ++ err = -ENODEV; ++ /* now complete initialisation */ ++ if(!AUDIO_ACTIVE(state)){ ++ if(state->hw_init){ ++ err = state->hw_init(); ++ if(err<0){ ++ if(file->f_mode & FMODE_WRITE){ ++ *os->drcmr = 0; ++ pxa_free_dma(os->dma_ch); ++ } ++ if(file->f_mode & FMODE_READ){ ++ *is->drcmr = 0; ++ pxa_free_dma(is->dma_ch); ++ } ++ goto out; ++ } ++ } ++ ++#ifdef CONFIG_PM ++ state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback); ++ if (state->pm_dev) ++ state->pm_dev->data = state; ++#endif ++ } ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("init data structure \n"); ++#endif ++ file->private_data = state; ++ file->f_op->release = audio_release; ++ file->f_op->write = audio_write; ++ file->f_op->read = audio_read; ++ file->f_op->mmap = audio_mmap; ++ file->f_op->poll = audio_poll; ++ file->f_op->ioctl = audio_ioctl; ++ file->f_op->llseek = no_llseek; ++ ++ if ((file->f_mode & FMODE_WRITE)) ++ { ++ state->wr_ref = 1; ++ os->fragsize = AUDIO_FRAGSIZE_DEFAULT; ++ os->nbfrags = AUDIO_NBFRAGS_DEFAULT; ++ os->output = 1; ++ os->mapped = 0; ++ init_waitqueue_head(&os->frag_wq); ++ init_waitqueue_head(&os->stop_wq); ++ *os->drcmr = os->dma_ch | DRCMR_MAPVLD; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("*os->drcmr=0x%lx\n", *os->drcmr); ++#endif ++ } ++ if (file->f_mode & FMODE_READ) ++ { ++ state->rd_ref = 1; ++ is->fragsize = AUDIO_FRAGSIZE_DEFAULT; ++ is->nbfrags = AUDIO_NBFRAGS_DEFAULT; ++ is->output = 0; ++ is->mapped = 0; ++ init_waitqueue_head(&is->frag_wq); ++ init_waitqueue_head(&is->stop_wq); ++ *is->drcmr = is->dma_ch | DRCMR_MAPVLD; ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("*is->drcmr=0x%lx\n", *is->drcmr); ++#endif ++ } ++ err = 0; ++ up(&state->sem); ++#ifdef EZX_OSS_AUDIO_DEBUG ++ printk("audio device open success\n"); ++#endif ++ return err; ++out: ++ up(&state->sem); ++ printk("audio device is busy or there is no audio device\n"); ++ return err; ++} ++ ++EXPORT_SYMBOL(cotulla_audio_attach); ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-audio.h linux-2.6.16.5-exz/sound/oss/ezx-audio.h +--- linux-2.6.16.5/sound/oss/ezx-audio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-audio.h 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,120 @@ ++/* ++ * linux/drivers/sound/ezx-audio.h ++ * ++ * ++ * Description: audio interface for ezx ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhou qiong June,2002 Created ++ * LiYong Sep 23,2003 Port from EZX ++ * Jin Lihong(w20076) Jan 02,2004,Libdd66088 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move all audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_DEBUG/EZX_OSS_AUDIO_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * ++ */ ++ ++#ifndef EZX_AUDIO_H ++#define EZX_AUDIO_H ++ ++ ++#define NO_HEADSET 0 ++#define MONO_HEADSET 1 ++#define STEREO_HEADSET 2 ++ ++#define OUT_ADJUST_GAIN 2 ++#define IN_ADJUST_GAIN 12 ++ ++#define ASSP_CLK (1<<20) ++#define ASSP_PINS (7<<17) ++ ++ ++#define PHONE_CODEC_DEFAULT_RATE 8000 ++#define PHONE_CODEC_16K_RATE 16000 ++ ++ ++#define STEREO_CODEC_8K_RATE 8000 ++#define STEREO_CODEC_11K_RATE 11025 ++#define STEREO_CODEC_12K_RATE 12000 ++#define STEREO_CODEC_16K_RATE 16000 ++#define STEREO_CODEC_22K_RATE 22050 ++#define STEREO_CODEC_24K_RATE 24000 ++#define STEREO_CODEC_32K_RATE 32000 ++#define STEREO_CODEC_44K_RATE 44100 ++#define STEREO_CODEC_48K_RATE 48000 ++ ++ ++typedef struct { ++ int offset; /* current buffer position */ ++ char *data; /* actual buffer */ ++ pxa_dma_desc *dma_desc; /* pointer to the starting desc */ ++ int master; /* owner for buffer allocation, contain size whn true */ ++}audio_buf_t; ++ ++typedef struct { ++ char *name; /* stream identifier */ ++ audio_buf_t *buffers; /* pointer to audio buffer array */ ++ u_int usr_frag; /* user fragment index */ ++ u_int dma_frag; /* DMA fragment index */ ++ u_int fragsize; /* fragment size */ ++ u_int nbfrags; /* number of fragments */ ++ u_int dma_ch; /* DMA channel number */ ++ dma_addr_t dma_desc_phys; /* phys addr of descriptor ring */ ++ u_int descs_per_frag; /* nbr descriptors per fragment */ ++ int bytecount; /* nbr of processed bytes */ ++ int getptrCount; /* value of bytecount last time anyone asked via GETxPTR*/ ++ int fragcount; /* nbr of fragment transitions */ ++ struct semaphore sem; /* account for fragment usage */ ++ wait_queue_head_t frag_wq; /* for poll(), etc. */ ++ wait_queue_head_t stop_wq; /* for users of DCSR_STOPIRQEN */ ++ u_long dcmd; /* DMA descriptor dcmd field */ ++ volatile u32 *drcmr; /* the DMA request channel to use */ ++ u_long dev_addr; /* device physical address for DMA */ ++ int mapped:1; /* mmap()'ed buffers */ ++ int output:1; /* 0 for input, 1 for output */ ++}audio_stream_t; ++ ++typedef struct { ++ audio_stream_t *output_stream; ++ audio_stream_t *input_stream; ++ int dev_dsp; /* audio device handle */ ++ int rd_ref:1; /* open reference for recording */ ++ int wr_ref:1; /* open reference for playback */ ++ int (*hw_init)(void); ++ void (*hw_shutdown)(void); ++ int (*client_ioctl)(struct inode *, struct file *, uint, ulong); ++ struct pm_dev *pm_dev; ++ struct semaphore sem; /* prevent races in attach/release */ ++}audio_state_t; ++ ++ ++extern int cotulla_audio_attach(struct inode *inode, struct file *file, audio_state_t *state); ++ ++/* for headset and mic interrupt routine*/ ++extern void headjack_change_interrupt_routine(int ch, void *dev_id, struct pt_regs *regs); ++extern void mic_change_interrupt_routine(int ch, void *dev_id, struct pt_regs *regs); ++extern int mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++ ++extern void set_pcap_telephone_codec(int port); ++extern void set_pcap_output_path(void); ++extern void set_pcap_input_path(void); ++ ++ ++extern void bluetoothaudio_open(void); ++extern void bluetoothaudio_close(void); ++ ++ ++#endif ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-common.c linux-2.6.16.5-exz/sound/oss/ezx-common.c +--- linux-2.6.16.5/sound/oss/ezx-common.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-common.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,216 @@ ++/* ++ * linux/drivers/sound/ezx-common.c ++ * ++ * ++ * Description: common functions implementation for ezx audio drivers ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Created, Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface ++ * Jin Lihong(w20076) Apr.24,2004,LIBee03164 reduce music noise, add new pathes for haptics ++ * Cheng Xuefeng(a2491c) June.24,2004,LIBdd95397 Add sound path for EMU PIHF ++ * ++ */ ++ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-common.h" ++ ++ ++int codec_output_gain = EZX_OSS_DEFAULT_OUTPUT_LOGICAL_GAIN; /* A2,loudspeaker, gain level */ ++output_enum codec_output_path = LOUDERSPEAKER_OUT; ++output_base_enum codec_output_base = PCAP_BASE; ++ ++int codec_input_gain = EZX_OSS_DEFAULT_AUDIG_LOGICAL_GAIN; /* A5,mic,gain=+17db */ ++input_enum codec_input_path = HANDSET_INPUT; ++int audioonflag = 0; ++int micinflag = 0; ++ ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ ++void (*mixer_close_input_path[INPUT_TOTAL_TYPES])(void) = ++{ ++ close_input_carkit, ++ close_input_handset, ++ close_input_headset, ++ close_input_funlight ++}; ++ ++void (*mixer_open_input_path[INPUT_TOTAL_TYPES])(void) = ++{ ++ open_input_carkit, ++ open_input_handset, ++ open_input_headset, ++ open_input_funlight ++}; ++ ++void (*mixer_close_output_path[][OUTPUT_TOTAL_TYPES])(void) = ++{ ++ { ++ close_output_pcap_headset, ++ close_output_pcap_louderspeaker, ++ close_output_pcap_earpiece, ++ close_output_pcap_carkit, ++ close_output_pcap_headjack, ++ close_output_pcap_bluetooth, ++ close_output_pcap_louderspeaker_mixed ++ }, ++ { ++ close_output_ma3_headset, ++ close_output_ma3_louderspeaker, ++ close_output_ma3_earpiece, ++ close_output_ma3_carkit, ++ close_output_ma3_headjack, ++ close_output_ma3_bluetooth, ++ close_output_ma3_louderspeaker_mixed ++ }, ++ { ++ close_output_fm_headset, ++ close_output_fm_louderspeaker, ++ close_output_fm_earpiece, ++ close_output_fm_carkit, ++ close_output_fm_headjack, ++ close_output_fm_bluetooth, ++ close_output_fm_louderspeaker_mixed ++ }, ++ { ++ close_output_mixed_headset, ++ close_output_mixed_louderspeaker, ++ close_output_mixed_earpiece, ++ close_output_mixed_carkit, ++ close_output_mixed_headjack, ++ close_output_mixed_bluetooth, ++ close_output_mixed_louderspeaker_mixed ++ } ++}; ++ ++int (*mixer_open_output_path[][OUTPUT_TOTAL_TYPES])(long val) = ++{ ++ { ++ open_output_pcap_headset, ++ open_output_pcap_louderspeaker, ++ open_output_pcap_earpiece, ++ open_output_pcap_carkit, ++ open_output_pcap_headjack, ++ open_output_pcap_bluetooth, ++ open_output_pcap_louderspeaker_mixed ++ }, ++ { ++ open_output_ma3_headset, ++ open_output_ma3_louderspeaker, ++ open_output_ma3_earpiece, ++ open_output_ma3_carkit, ++ open_output_ma3_headjack, ++ open_output_ma3_bluetooth, ++ open_output_ma3_louderspeaker_mixed ++ }, ++ { ++ open_output_fm_headset, ++ open_output_fm_louderspeaker, ++ open_output_fm_earpiece, ++ open_output_fm_carkit, ++ open_output_fm_headjack, ++ open_output_fm_bluetooth, ++ open_output_fm_louderspeaker_mixed ++ }, ++ { ++ open_output_mixed_headset, ++ open_output_mixed_louderspeaker, ++ open_output_mixed_earpiece, ++ open_output_mixed_carkit, ++ open_output_mixed_headjack, ++ open_output_mixed_bluetooth, ++ open_output_mixed_louderspeaker_mixed ++ } ++}; ++#endif /* CONFIG_ARCH_EZX_E680 */ ++ ++ ++#ifdef CONFIG_ARCH_EZX_A780 ++void (*mixer_close_input_path[INPUT_TOTAL_TYPES])(void) = ++{ ++ close_input_carkit, ++ close_input_handset, ++#if EMU_PIHF_FEATURE ++ close_input_headset, ++ close_input_pihf_carkit ++#else ++ close_input_headset ++#endif ++ ++}; ++ ++void (*mixer_open_input_path[INPUT_TOTAL_TYPES])(void) = ++{ ++ open_input_carkit, ++ open_input_handset, ++#if EMU_PIHF_FEATURE ++ open_input_headset, ++ open_input_pihf_carkit ++#else ++ open_input_headset ++#endif ++}; ++ ++void (*mixer_close_output_path[][OUTPUT_TOTAL_TYPES])(void) = ++{ ++ { ++ close_output_pcap_headset, ++ close_output_pcap_louderspeaker, ++ close_output_pcap_earpiece, ++ close_output_pcap_carkit, ++ close_output_pcap_headjack, ++#if EMU_PIHF_FEATURE ++ close_output_pcap_bluetooth, ++ close_output_pcap_pihf_carkit ++#else ++ close_output_pcap_bluetooth ++#endif ++ } ++}; ++ ++int (*mixer_open_output_path[][OUTPUT_TOTAL_TYPES])(long val) = ++{ ++ { ++ open_output_pcap_headset, ++ open_output_pcap_louderspeaker, ++ open_output_pcap_earpiece, ++ open_output_pcap_carkit, ++ open_output_pcap_headjack, ++#if EMU_PIHF_FEATURE ++ open_output_pcap_bluetooth, ++ open_output_pcap_pihf_carkit ++#else ++ open_output_pcap_bluetooth ++#endif ++ } ++}; ++#endif ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-common.h linux-2.6.16.5-exz/sound/oss/ezx-common.h +--- linux-2.6.16.5/sound/oss/ezx-common.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-common.h 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,161 @@ ++/* ++ * linux/drivers/sound/ezx-common.h ++ * ++ * ++ * Description: header file for ezx-common.c ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 12,2004,LIBdd68327 Created,Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface ++ * Jin Lihong(w20076) Apr.24,2004,LIBee03164 reduce music noise, add new pathes for haptics ++ * Li Yong(w19946) Apr.22.2004.LIBee02702 Add EMU carKit ++ * Cheng Xuefeng(a2491c) Jun.15.2004,LIBdd95397 Support EMU PIHF feature ++ * ++ */ ++ ++#ifndef EZX_COMMON_H ++#define EZX_COMMON_H ++ ++#include "ezx-e680.h" ++#include "ezx-a780.h" ++#include "../../drivers/misc/ezx/ssp_pcap.h" ++ ++#define EZXOSS_EMERG "Snd driver w20076 <0 EMERG>: " /* system is unusable */ ++#define EZXOSS_ALERT "Snd driver w20076 <1 ALERT>: " /* action must be taken immediately */ ++#define EZXOSS_CRIT "Snd driver w20076 <2 CRIT>: " /* critical conditions */ ++#define EZXOSS_ERR "Snd driver w20076 <3 ERR>: " /* error conditions */ ++#define EZXOSS_WARNING "Snd driver w20076 <4 WARNING>: " /* warning conditions */ ++#define EZXOSS_NOTICE "Snd driver w20076 <5 NOTICE>: " /* normal but significant condition */ ++#define EZXOSS_INFO "Snd driver w20076 <6 INFO>: " /* informational */ ++#define EZXOSS_DEBUG "Snd driver w20076 <7 DEBUG>: " /* debug-level messages */ ++ ++#define MONODEVOPENED ( audioonflag & (PHONE_DEVICE|DSP16_DEVICE|AUDIO_DEVICE) ) ++#define PHONEDEVOPENED ( audioonflag & PHONE_DEVICE ) ++ ++#define EZX_OSS_MIN_LOGICAL_GAIN 0 ++#define EZX_OSS_MAX_LOGICAL_GAIN 100 ++#define EZX_OSS_DEFAULT_OUTPUT_LOGICAL_GAIN 74 /* +9db, same as a760 */ ++#define EZX_OSS_DEFAULT_AUDIG_LOGICAL_GAIN 55 /* +17db, same as a760 */ ++#define EZX_OSS_DEFAULT_MIC2IG_LOGICAL_GAIN 55 /* +17db, same as a760 */ ++ ++#define PCAP_OUTPUT_GAIN_MIN_REG_VAL 0 ++#define PCAP_OUTPUT_GAIN_MAX_REG_VAL 15 ++#define PCAP_INPUT_GAIN_MIN_REG_VAL 0 ++#define PCAP_INPUT_GAIN_MAX_REG_VAL 31 ++/*EMU CarKit Mute control signal */ ++#define EIHF_UNMUTE 0x01 ++#define EIHF_MUTE 0x00 ++ ++#define DEFAULT_USB_MODE 0x00 ++#define MONO_AUDIO_MODE 0x02 ++#define SETERO_AUDIO_MODE 0x03 ++ ++#define PCAP_OUTPUT_GAIN_REG_VAL_FROM_LOGIC (codec_output_gain*PCAP_OUTPUT_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++#define PCAP_INPUT_AUDIG_REG_VAL_FROM_LOGIC (codec_input_gain*PCAP_INPUT_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++#define PCAP_INPUT_MIC2IG_REG_VAL_FROM_LOGIC (codec_input_gain*PCAP_INPUT_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++ ++#ifdef EMU_PIHF_FEATURE ++typedef enum{ ++ HEADSET_OUT, /* ear-phone : stereo headset */ ++ LOUDERSPEAKER_OUT, /* A2_OUTPUT in a760 */ ++ EARPIECE_OUT, /* A1_OUTPUT in a760 */ ++ CARKIT_OUT, /* A4_OUTPUT in a760 */ ++ HEADJACK_OUT, /* mono headjack, HEADJACK_OUTPUT in a760 */ ++ BLUETOOTH_OUT, /* bluetooth headset */ ++ PIHF_CARKIT_OUT /* A4_OUTPUT in a760 */ ++}output_enum; ++#else /* EMU_PIHF_FEATURE */ ++typedef enum{ ++ HEADSET_OUT, /* ear-phone : stereo headset */ ++ LOUDERSPEAKER_OUT, /* A2_OUTPUT in a760 */ ++ EARPIECE_OUT, /* A1_OUTPUT in a760 */ ++ CARKIT_OUT, /* A4_OUTPUT in a760 */ ++ HEADJACK_OUT, /* mono headjack, HEADJACK_OUTPUT in a760 */ ++ BLUETOOTH_OUT, /* bluetooth headset */ ++ LOUDERSPEAKER_MIXED_OUT /* e680 louderspeaker out, boomer input is stereo+mono, mono is aimed for haptics signals */ ++}output_enum; ++#endif /* EMU_PIHF_FEAURE */ ++ ++typedef enum{ ++ PCAP_BASE = 0x0000 , /* used to tell that we are setting the PCAP */ ++ MA3_BASE = 0x0100 , /* MA3 Midi device */ ++ FM_BASE = 0x0200 , /* FM radio device */ ++ MIXED_BASE = 0x0300 /* Both MA3 device and PCAP device are used */ ++}output_base_enum; ++ ++#ifdef EMU_PIHF_FEATURE ++typedef enum{ ++ CARKIT_INPUT, /* EXT_MIC */ ++ HANDSET_INPUT , /* A5 */ ++ HEADSET_INPUT , /* A3 */ ++ PIHF_CARKIT_INPUT /* EXT_MIC */ ++}input_enum; ++#else /* EMU_PIHF_FEATURE */ ++typedef enum{ ++ CARKIT_INPUT, /* EXT_MIC */ ++ HANDSET_INPUT , /* A5 */ ++ HEADSET_INPUT , /* A3 */ ++ FUNLIGHT_INPUT /* E680 funlight */ ++}input_enum; ++#endif /* EMU_PIHF_FEATURE */ ++ ++ ++#define INPUT_PATH_MIN CARKIT_INPUT ++ ++#ifdef CONFIG_PXA_EZX_A780 ++#ifdef EMU_PIHF_FEATURE ++#define INPUT_PATH_MAX PIHF_CARKIT_INPUT ++#define INPUT_TOTAL_TYPES 4 /* = HEADSET_INPUT+1 */ ++#define OUTPUT_PATH_MAX PIHF_CARKIT_OUT ++#define OUTPUT_BASE_MAX PCAP_BASE ++#define OUTPUT_TOTAL_TYPES 7 /* = BLUETOOTH_OUT+1 */ ++#else /* EMU_PIHF_FEATURE */ ++#define INPUT_PATH_MAX HEADSET_INPUT ++#define INPUT_TOTAL_TYPES 3 /* = HEADSET_INPUT+1 */ ++#define OUTPUT_PATH_MAX BLUETOOTH_OUT ++#define OUTPUT_BASE_MAX PCAP_BASE ++#define OUTPUT_TOTAL_TYPES 6 /* = BLUETOOTH_OUT+1 */ ++#endif /* EMU_PIHF_FEATURE */ ++#endif ++ ++#ifdef CONFIG_PXA_EZX_E680 ++#define INPUT_PATH_MAX FUNLIGHT_INPUT ++#define INPUT_TOTAL_TYPES 4 /* = FUNLIGHT_INPUT + 1 */ ++#define OUTPUT_PATH_MAX LOUDERSPEAKER_MIXED_OUT ++#define OUTPUT_BASE_MAX MIXED_BASE ++#define OUTPUT_TOTAL_TYPES 7 /* = LOUDERSPEAKER_MIXED_OUT+1 */ ++#endif ++ ++#define OUTPUT_BASE_MEANINGFUL_START_BIT 8 ++#define OUTPUT_BASE_TYPE(x) (x >>OUTPUT_BASE_MEANINGFUL_START_BIT) ++#define OUTPUT_BASE_TOTAL_TYPES (OUTPUT_BASE_MAX>>OUTPUT_BASE_MEANINGFUL_START_BIT +1) ++#define GET_OUTPUT_BASE(x) (x&0xFF00) ++#define GET_OUTPUT_PATH(x) (x&0x00FF) ++ ++ ++extern int codec_output_gain, codec_input_gain; ++extern output_enum codec_output_path; ++extern input_enum codec_input_path; ++extern output_base_enum codec_output_base; ++extern int audioonflag; ++extern int micinflag; ++ ++extern void (*mixer_close_output_path[][OUTPUT_TOTAL_TYPES])(void); ++extern int (*mixer_open_output_path[][OUTPUT_TOTAL_TYPES])(long val); ++extern void (*mixer_close_input_path[INPUT_TOTAL_TYPES])(void); ++extern void (*mixer_open_input_path[INPUT_TOTAL_TYPES])(void); ++ ++ ++#endif ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-e680.c linux-2.6.16.5-exz/sound/oss/ezx-e680.c +--- linux-2.6.16.5/sound/oss/ezx-e680.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-e680.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,1733 @@ ++/* ++ * linux/drivers/sound/ezx-e680.c ++ * ++ * ++ * Description: Motorola e680 phone specific functions implementation for audio drivers ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Created, Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90336 play music noise tmp solution ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * Jin Lihong(w20076) Apr.20,2004,LIBee01165 reduce noise ++ * Jin Lihong(w20076) Apr.24,2004,LIBee03164 reduce music noise, add new pathes for haptics ++ * Li Yong(w19946) Apr.23.2004.LIBee02702 Add EMU Carkit ++ * Jin Lihong(w20076) Jun.08,2004,libee14656 change boomer input path for mono sound ++ * Jin Lihong(w20076) Jun.15,2004,LIBee21625 boomer's power management ++ * Jin Lihong(w20076) Jun.22,2004,LIBee24284 mixer power save ++ * Wu Hongxing(w20691)Jul.07,2004 LIBee29664 ap 13m clock usage. ++ * Jin Lihong(w20076) Aug.11,2004,LIBff01482 mixer power on/off sequence optimize ++ * ++ */ ++ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++#include <linux/delay.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-common.h" ++ ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ ++EXPORT_SYMBOL(poweron_mixer); ++EXPORT_SYMBOL(shutdown_mixer); ++EXPORT_SYMBOL(kernel_clr_oscc_13m_clock); ++EXPORT_SYMBOL(kernel_set_oscc_13m_clock); ++ ++static DECLARE_MUTEX(ezx_mixer_mutex); ++ ++ ++ ++#define BOOMER_MONO_VOL_REG_PREFIX 0x00 ++#define BOOMER_STEREO_LEFT_VOL_REG_PREFIX 0x40 ++#define BOOMER_STEREO_RIGHT_VOL_REG_PREFIX 0x80 ++#define BOOMER_MODE_CONTROL_REG_PREFIX 0xC0 ++ ++#define BOOMER_MONO_GAIN_MIN_REG_VAL 0 ++#define BOOMER_MONO_GAIN_MAX_REG_VAL 31 ++#define BOOMER_MONO_GAIN_DEFAULT_REG_VAL 15 ++#define BOOMER_MONO_GAIN_DEFAULT_FIXED_REG_VAL 23 ++#define BOOMER_MONO_GAIN_MIXED_INPUT_CASE_REG_VAL 15 /* when in a special use case: mono input for haptics, ++ stereo input for audio signals */ ++ ++#define BOOMER_STEREO_LEFT_GAIN_MIN_REG_VAL 0 ++#define BOOMER_STEREO_LEFT_GAIN_MAX_REG_VAL 31 ++#define BOOMER_STEREO_LEFT_GAIN_DEFAULT_REG_VAL 15 ++#define BOOMER_STEREO_LEFT_GAIN_DEFAULT_FIXED_REG_VAL 27 ++#define BOOMER_STEREO_LEFT_GAIN_MIXED_INPUT_CASE_REG_VAL 27 /* when in a special use case: mono input for haptics, ++ stereo input for audio signals */ ++ ++#define BOOMER_STEREO_RIGHT_GAIN_MIN_REG_VAL 0 ++#define BOOMER_STEREO_RIGHT_GAIN_MAX_REG_VAL 31 ++#define BOOMER_STEREO_RIGHT_GAIN_DEFAULT_REG_VAL 15 ++#define BOOMER_STEREO_RIGHT_GAIN_DEFAULT_FIXED_REG_VAL 27 ++#define BOOMER_STEREO_RIGHT_GAIN_MIXED_INPUT_CASE_REG_VAL 27 /* when in a special use case: mono input for haptics, ++ stereo input for audio signals */ ++ ++#define BOOMER_OUTPUT_GAIN_MONO_REG_VAL_FROM_LOGIC (codec_output_gain*BOOMER_MONO_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++#define BOOMER_OUTPUT_GAIN_STEREO_LEFT_REG_VAL_FROM_LOGIC (codec_output_gain*BOOMER_STEREO_LEFT_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++#define BOOMER_OUTPUT_GAIN_STEREO_RIGHT_REG_VAL_FROM_LOGIC (codec_output_gain*BOOMER_STEREO_RIGHT_GAIN_MAX_REG_VAL/EZX_OSS_MAX_LOGICAL_GAIN) ++ ++#define BOOMER_LOUDER_SPEAKER_3D_OFF 0X00 /* bit LD5 */ ++#define BOOMER_LOUDER_SPEAKER_3D_ON 0X20 ++#define BOOMER_HEADPHONE_3D_OFF 0X00 /* bit RD5 */ ++#define BOOMER_HEADPHONE_3D_ON 0X20 ++ ++#define BOOMER_SHUTDOWN 0X00 /* bit CD3 ~ CD0 */ ++#define BOOMER_IN_MONO_OUT_MONO_EARPIECE 0X01 ++#define BOOMER_IN_MONO_OUT_LOUDER_SPEAKER 0X02 ++#define BOOMER_IN_MONO_OUT_LOUDER_SPEAKER_AND_HEADPHONE 0X03 ++#define BOOMER_IN_MONO_OUT_HEADPHONE 0X04 ++#define BOOMER_IN_MONO_OUT_MONO_LINEOUT 0X05 ++#define BOOMER_IN_STEREO_OUT_MONO_EARPIECE 0X06 ++#define BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER 0X07 ++#define BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER_AND_HEADPHONE 0X08 ++#define BOOMER_IN_STEREO_OUT_HEADPHONE 0X09 ++#define BOOMER_IN_STEREO_OUT_MONO_LINEOUT 0X0a ++#define BOOMER_IN_MONO_AND_STEREO_OUT_MONO_EARPIECE 0X0b ++#define BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER 0X0c ++#define BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER_AND_HEADPHONE 0X0d ++#define BOOMER_IN_MONO_AND_STEREO_OUT_HEADPHONE 0X0e ++#define BOOMER_IN_MONO_AND_STEREO_OUT_MONO_LINEOUT 0X0f ++ ++#define BOOMER_FAST_WAKEUP 0X00 /* bit CD5 */ ++#define BOOMER_SLOW_WAKEUP 0X20 ++ ++#define BOOMER_EARPIECE_GAIN_SMALL_OPTION 0X00 /* bit CD4 */ ++#define BOOMER_EARPIECE_GAIN_LARGE_OPTION 0X10 ++ ++ ++typedef struct { ++ u8 monovol; /* mono volume */ ++ u8 leftvol; /* stereo left volume */ ++ u8 rightvol; /* stereo right volume */ ++ u8 path; /* boomer path setup */ ++ u8 speaker3d; ++ u8 headphone3d; ++ u8 wakeuptime; /* fast or slow wakeup setting */ ++ u8 earpiecegaintable; /* earpiece gain table select */ ++} e680_boomer; ++ ++ ++static e680_boomer e680boomer; ++static u32 gpio_flt_sel_status; ++u32 gpio_va_sel_status; ++ ++static void set_boomer_mono_vol_reg( void ); ++static void set_boomer_stereo_left_vol_reg(void); ++static void set_boomer_stereo_right_vol_reg(void); ++static void set_boomer_mode_control_reg(void); ++ ++static void write_boomer(const char *buf, size_t count); ++extern int mixer_write(const char *buf, size_t count); ++ ++ ++void e680_boomer_init(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "e680 boomer init\n"); ++#endif ++ ++ e680boomer.monovol = BOOMER_MONO_GAIN_DEFAULT_REG_VAL; ++ e680boomer.leftvol = BOOMER_STEREO_LEFT_GAIN_DEFAULT_REG_VAL; ++ e680boomer.rightvol = BOOMER_STEREO_RIGHT_GAIN_DEFAULT_REG_VAL; ++ e680boomer.path = BOOMER_IN_MONO_OUT_MONO_LINEOUT; ++ e680boomer.speaker3d = BOOMER_LOUDER_SPEAKER_3D_ON; ++ e680boomer.headphone3d = BOOMER_HEADPHONE_3D_ON; ++ e680boomer.wakeuptime = BOOMER_FAST_WAKEUP; ++ e680boomer.earpiecegaintable = BOOMER_EARPIECE_GAIN_LARGE_OPTION; ++ ++ set_boomer_mode_control_reg(); ++ set_boomer_mono_vol_reg(); ++ set_boomer_stereo_left_vol_reg(); ++ set_boomer_stereo_right_vol_reg(); ++} ++ ++ ++void e680_boomer_shutdown(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "e680 boomer shutdown.\n"); ++#endif ++ ++ e680boomer.path = BOOMER_SHUTDOWN; ++ set_boomer_mode_control_reg(); ++} ++ ++ ++void e680_boomer_path_mono_lineout(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " set E680 boomer path to mono input mono lineout.\n"); ++#endif ++ ++ e680boomer.path = BOOMER_IN_MONO_OUT_MONO_LINEOUT; ++ set_boomer_mode_control_reg(); ++} ++ ++ ++void e680_boomer_path_tmp_mono_lineout(void) ++{ ++ u8 mode; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " mute E680 boomer.\n"); ++#endif ++ ++ mode = BOOMER_MODE_CONTROL_REG_PREFIX | BOOMER_IN_MONO_OUT_MONO_LINEOUT ++ | e680boomer.wakeuptime | e680boomer.earpiecegaintable; ++ ++ write_boomer(&mode, 1); ++} ++ ++ ++void e680_boomer_path_tmp_shutdown(void) ++{ ++ u8 mode; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " E680 boomer path set to tmp shutdown..\n"); ++#endif ++ ++ mode = BOOMER_MODE_CONTROL_REG_PREFIX | BOOMER_SHUTDOWN ++ | e680boomer.wakeuptime | e680boomer.earpiecegaintable; ++ ++ write_boomer(&mode, 1); ++} ++ ++ ++void e680_boomer_path_restore(void) ++{ ++ u8 mode; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " E680 boomer path restore: path = 0X%X \n", e680boomer.path); ++#endif ++ mode = BOOMER_MODE_CONTROL_REG_PREFIX | e680boomer.path | e680boomer.wakeuptime | e680boomer.earpiecegaintable; ++ write_boomer(&mode, 1); ++} ++ ++ ++static void set_boomer_mono_vol_reg( void ) ++{ ++ u8 vol; ++ ++ vol = BOOMER_MONO_VOL_REG_PREFIX | e680boomer.monovol; ++ write_boomer(&vol, 1); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "set e680 boomer mono volume register,vol=0x%2X \n", vol); ++#endif ++} ++ ++ ++static void set_boomer_stereo_left_vol_reg(void) ++{ ++ u8 vol; ++ ++ vol = BOOMER_STEREO_LEFT_VOL_REG_PREFIX | e680boomer.leftvol | e680boomer.speaker3d; ++ write_boomer(&vol, 1); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "set e680 boomer stereo left volume register,vol=0x%2X \n", vol); ++#endif ++} ++ ++ ++static void set_boomer_stereo_right_vol_reg(void) ++{ ++ u8 vol; ++ ++ vol = BOOMER_STEREO_RIGHT_VOL_REG_PREFIX | e680boomer.rightvol | e680boomer.headphone3d; ++ write_boomer(&vol, 1); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "set e680 boomer stereo right volume register,vol=0x%2X \n", vol); ++#endif ++} ++ ++ ++static void set_boomer_mode_control_reg(void) ++{ ++ u8 mode; ++ ++ mode = BOOMER_MODE_CONTROL_REG_PREFIX | e680boomer.path | e680boomer.wakeuptime | e680boomer.earpiecegaintable; ++ write_boomer(&mode, 1); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "set e680 boomer mode control register,mode=0x%2X \n", mode); ++#endif ++} ++ ++ ++static void write_boomer(const char *buf, size_t count) ++{ ++ int ret, i = 0; ++ size_t written = 0; ++ ++ while(written<count) ++ { ++ ret = mixer_write(buf+written, count-written); ++ written+=ret; ++ i++; ++ if( i>2 ) ++ break; ++ } ++ if( written < count ) ++ printk(EZXOSS_ERR "write boomer failed.\n"); ++} ++ ++ ++void poweron_mixer( audio_dev_type type ) ++{ ++ down(&ezx_mixer_mutex); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device wants to power on the mixer hardware.\n", type); ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device has already powered on the mixer hardware.\n", audioonflag); ++#endif ++ ++ audioonflag |= type; ++ ++ if( MIXERISSTEREO == type ){ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device is powering on the mixer hardware.\n", type); ++#endif ++ ++ if( (type==MIDI_DEVICE) || (type==FM_DEVICE) ) ++ mute_output_to_avoid_pcap_noise(); ++ ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++ ++ /* (1) set pcap audio power V2_EN_2(OR WITH V2_EN) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_V2_EN_2); ++ ++ /* (6) enable output_path and set gain */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP); /* disable codec bypass */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ST_DAC_SW); /* close stereo switch */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CDC_SW); /* open telephone codec path into right PGA */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); /* close PGA_INR into PGA */ ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN); /* enable right PGA */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); /* enable left PGA */ ++ ++ if( (type==MIDI_DEVICE) || (type==FM_DEVICE) ) ++ undo_mute_output_to_avoid_pcap_noise(); ++ } ++ ++ up(&ezx_mixer_mutex); ++} ++ ++ ++void shutdown_mixer( audio_dev_type type ) ++{ ++ down(&ezx_mixer_mutex); ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device wants to shut down the mixer hardware.\n", type); ++#endif ++ ++ if( audioonflag == type ){ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device is shutting down the mixer hardware.\n", type); ++#endif ++ ++ e680_boomer_path_mono_lineout(); /* mute hw noise and save power for e680 */ ++ ++ /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER, SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ } ++ ++ audioonflag &= ~type; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 No. 0x%X device is still using the mixer hardware.\n", audioonflag); ++#endif ++ ++ up(&ezx_mixer_mutex); ++} ++ ++ ++void mixer_not_in_use(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " E680 mixer not in use.\n"); ++#endif ++ ++ (*mixer_close_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(); ++ (*mixer_close_input_path[codec_input_path])(); ++ ++ if( micinflag == 0 ) /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER, SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ ++ e680_boomer_path_mono_lineout(); ++} ++ ++ ++void set_output_gain_hw_reg(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "set output gain hw register. \n"); ++#endif ++ ++ SSP_PCAP_AUDOG_set( PCAP_OUTPUT_GAIN_REG_VAL_FROM_LOGIC ); ++ ++ if( e680boomer.path == BOOMER_SHUTDOWN ){ ++ ; ++ } ++ else if( e680boomer.path <= BOOMER_IN_MONO_OUT_MONO_LINEOUT ){ ++ e680boomer.monovol = BOOMER_MONO_GAIN_DEFAULT_FIXED_REG_VAL; ++ set_boomer_mono_vol_reg(); ++ } ++ else if( e680boomer.path <= BOOMER_IN_STEREO_OUT_MONO_LINEOUT ){ ++ e680boomer.leftvol = BOOMER_STEREO_LEFT_GAIN_DEFAULT_FIXED_REG_VAL; ++ e680boomer.rightvol = BOOMER_STEREO_RIGHT_GAIN_DEFAULT_FIXED_REG_VAL; ++ set_boomer_stereo_left_vol_reg(); ++ set_boomer_stereo_right_vol_reg(); ++ } ++ else{ ++ if( e680boomer.path == BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER ){ ++ e680boomer.monovol = BOOMER_MONO_GAIN_MIXED_INPUT_CASE_REG_VAL; ++ e680boomer.leftvol = BOOMER_STEREO_LEFT_GAIN_MIXED_INPUT_CASE_REG_VAL; ++ e680boomer.rightvol = BOOMER_STEREO_RIGHT_GAIN_MIXED_INPUT_CASE_REG_VAL; ++ } ++ else{ ++ e680boomer.monovol = BOOMER_MONO_GAIN_DEFAULT_FIXED_REG_VAL; ++ e680boomer.leftvol = BOOMER_STEREO_LEFT_GAIN_DEFAULT_FIXED_REG_VAL; ++ e680boomer.rightvol = BOOMER_STEREO_RIGHT_GAIN_DEFAULT_FIXED_REG_VAL; ++ } ++ set_boomer_mono_vol_reg(); ++ set_boomer_stereo_left_vol_reg(); ++ set_boomer_stereo_right_vol_reg(); ++ } ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "codec_output_gain=%d\n", codec_output_gain); ++#endif ++} ++ ++ ++void set_input_gain_hw_reg(void) ++{ ++ SSP_PCAP_AUDIG_set( PCAP_INPUT_AUDIG_REG_VAL_FROM_LOGIC ); ++ ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "codec_input_gain=%d\n", codec_input_gain ); ++#endif ++} ++ ++ ++void set_boomer_3d_status(boomer_3d_status status) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "set boomer 3d status.\n"); ++#endif ++ ++ switch(status) ++ { ++ case LOUDERSPEAKER_ON_HEADSET_OFF_3D: ++ e680boomer.speaker3d = BOOMER_LOUDER_SPEAKER_3D_ON; ++ e680boomer.headphone3d = BOOMER_HEADPHONE_3D_OFF; ++ break; ++ ++ case LOUDERSPEAKER_OFF_HEADSET_ON_3D: ++ e680boomer.speaker3d = BOOMER_LOUDER_SPEAKER_3D_OFF; ++ e680boomer.headphone3d = BOOMER_HEADPHONE_3D_ON; ++ break; ++ ++ case LOUDERSPEAKER_OFF_HEADSET_OFF_3D: ++ e680boomer.speaker3d = BOOMER_LOUDER_SPEAKER_3D_OFF; ++ e680boomer.headphone3d = BOOMER_HEADPHONE_3D_OFF; ++ break; ++ ++ case LOUDERSPEAKER_ON_HEADSET_ON_3D: ++ default: ++ e680boomer.speaker3d = BOOMER_LOUDER_SPEAKER_3D_ON; ++ e680boomer.headphone3d = BOOMER_HEADPHONE_3D_ON; ++ } ++ ++ set_boomer_stereo_left_vol_reg(); ++ set_boomer_stereo_right_vol_reg(); ++} ++ ++ ++boomer_3d_status get_boomer_3d_status(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "get boomer 3d status.\n"); ++#endif ++ ++ if(e680boomer.speaker3d == BOOMER_LOUDER_SPEAKER_3D_ON){ ++ if(e680boomer.headphone3d == BOOMER_HEADPHONE_3D_ON) ++ return LOUDERSPEAKER_ON_HEADSET_ON_3D; ++ else ++ return LOUDERSPEAKER_ON_HEADSET_OFF_3D; ++ } ++ else{ ++ if(e680boomer.headphone3d == BOOMER_HEADPHONE_3D_ON) ++ return LOUDERSPEAKER_OFF_HEADSET_ON_3D; ++ else ++ return LOUDERSPEAKER_OFF_HEADSET_OFF_3D; ++ } ++} ++ ++ ++void set_gpio_va_sel_out_high(void) ++{ ++ set_GPIO_mode(GPIO_VA_SEL_BUL | GPIO_OUT); ++ set_GPIO(GPIO_VA_SEL_BUL); ++ PGSR(GPIO_VA_SEL_BUL) |= GPIO_bit(GPIO_VA_SEL_BUL); ++ gpio_va_sel_status = 1; ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "set VA_SEL high. \n"); ++#endif ++} ++ ++ ++void set_gpio_va_sel_out_low(void) ++{ ++ set_GPIO_mode(GPIO_VA_SEL_BUL | GPIO_OUT); ++ clr_GPIO(GPIO_VA_SEL_BUL); ++ PGSR(GPIO_VA_SEL_BUL) &= ~GPIO_bit(GPIO_VA_SEL_BUL); ++ gpio_va_sel_status = 0; ++#ifdef EZX_OSS_DEBUG ++ printk( EZXOSS_DEBUG "set VA_SEL low. \n"); ++#endif ++} ++ ++ ++void close_input_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input carkit. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++void close_input_handset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input handset. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON1); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_MUX); ++} ++ ++ ++void close_input_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input headset. \n"); ++#endif ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_MUX); ++} ++ ++ ++void close_input_funlight(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close input funlight. \n"); ++#endif ++ ++ /* disable PCAP codec */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB); ++ /* set fsync, tx, bitclk are tri-stated */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CD_TS); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++void open_input_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input carkit. \n"); ++#endif ++ codec_input_path = CARKIT_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++void open_input_handset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input handset. \n"); ++#endif ++ ++ codec_input_path = HANDSET_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON1); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A5_MUX); ++} ++ ++ ++void open_input_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input headset. \n"); ++#endif ++ ++ codec_input_path = HEADSET_INPUT; ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_A3_MUX); ++} ++ ++ ++void open_input_funlight(void) ++{ ++ unsigned long ssp_pcap_register_val; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open input funlight. \n"); ++#endif ++ ++ codec_input_path = FUNLIGHT_INPUT; ++ ++ set_gpio_va_sel_out_high(); ++ ++ /* (2) set codec sample rate(FS_8K_16K=0) */ ++ /* CDC_CLK(000=13MHZ) bitclk output(SMB=0) audio IO1(DIG_AUD_IN=1) */ ++ ssp_pcap_register_val = PCAP_CDC_CLK_IN_13M0; ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_CODEC_REGISTER, ssp_pcap_register_val); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB); /* codec master */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); /* 8K sample rate */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_DIG_AUD_IN); /* DAI0 */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDIHPF); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_AUDOHPF); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_INV); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_INV); ++ ++ /*(3) reset digital filter(DF_RESET=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_ADITH); ++ /* (4) enable pcap clk(CDC_CLK_EN=1),enable CODEC(CDC_EN=1) */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_CD_BYP); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ mdelay(1); /* specified enable time */ ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_EXT_MIC_MUX); ++} ++ ++ ++void close_output_pcap_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap headset. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++} ++ ++ ++void close_output_pcap_louderspeaker(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap louderspeaker. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++} ++ ++ ++void close_output_pcap_earpiece(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap earpiece. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1_EN); ++} ++ ++ ++void close_output_pcap_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap carkit. \n"); ++#endif ++ e680_boomer_path_mono_lineout(); ++ EIHF_Mute(EIHF_MUTE); //Mute EIHF ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ++ Set_EMU_Mux_Switch(DEFAULT_USB_MODE); ++} ++ ++ ++void close_output_pcap_headjack(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap headjack. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++} ++ ++ ++void close_output_pcap_bluetooth(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap bluetooth. \n"); ++#endif ++ ++} ++ ++ ++void close_output_pcap_louderspeaker_mixed(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output pcap louderspeaker mixed. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++} ++ ++ ++void close_output_ma3_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 headset. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_ma3_louderspeaker(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 louderspeaker. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_ma3_earpiece(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 earpiece. \n"); ++#endif ++ ++} ++ ++ ++void close_output_ma3_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 carkit. \n"); ++#endif ++ ++} ++ ++ ++void close_output_ma3_headjack(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 headjack. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_ma3_bluetooth(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 bluetooth. \n"); ++#endif ++ ++} ++ ++ ++void close_output_ma3_louderspeaker_mixed(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output ma3 louderspeaker mixed. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_fm_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm headset. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_fm_louderspeaker(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm louderspeaker. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_fm_earpiece(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm earpiece. \n"); ++#endif ++ ++} ++ ++ ++void close_output_fm_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm carkit. \n"); ++#endif ++ ++} ++ ++ ++void close_output_fm_headjack(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm headjack. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_fm_bluetooth(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm bluetooth. \n"); ++#endif ++ ++} ++ ++ ++void close_output_fm_louderspeaker_mixed(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output fm louderspeaker mixed. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_mixed_headset(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed headset. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_mixed_louderspeaker(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed louderspeaker. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_mixed_earpiece(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed earpiece. \n"); ++#endif ++ ++} ++ ++ ++void close_output_mixed_carkit(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed carkit. \n"); ++#endif ++ ++} ++ ++ ++void close_output_mixed_headjack(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed headjack. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++void close_output_mixed_bluetooth(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed bluetooth. \n"); ++#endif ++ ++} ++ ++ ++void close_output_mixed_louderspeaker_mixed(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "close output mixed louderspeaker mixed. \n"); ++#endif ++ ++ e680_boomer_path_mono_lineout(); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++} ++ ++ ++int open_output_pcap_headset(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap headset. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_louderspeaker(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap louderspeaker. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_earpiece(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap earpiece. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_MONO_OUT_MONO_LINEOUT; ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1_EN); ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_carkit(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap carkit. \n"); ++#endif ++ ++ Set_EMU_Mux_Switch(MONO_AUDIO_MODE); ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path=BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ EIHF_Mute(EIHF_UNMUTE); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_headjack(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap headjack. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_pcap_bluetooth(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap bluetooth. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_pcap_louderspeaker_mixed(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output pcap louderspeaker mixed. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ set_boomer_mode_control_reg(); ++ ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_ma3_headset(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 headset. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_ma3_louderspeaker(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 louderspeaker. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_ma3_earpiece(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 earpiece. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_ma3_carkit(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 carkit. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_ma3_headjack(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 headjack. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_ma3_bluetooth(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 bluetooth. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_ma3_louderspeaker_mixed(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output ma3 louderspeaker mixed. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_fm_headset(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm headset. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_fm_louderspeaker(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm louderspeaker. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_fm_earpiece(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm earpiece. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_fm_carkit(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm carkit. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_fm_headjack(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm headjack. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_fm_bluetooth(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm bluetooth. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_fm_louderspeaker_mixed(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output fm louderspeaker mixed. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_mixed_headset(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed headset. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_mixed_louderspeaker(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed louderspeaker. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_mixed_earpiece(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed earpiece. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_mixed_carkit(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed carkit. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_mixed_headjack(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed headjack. \n"); ++#endif ++ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL_6DB); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_STEREO_OUT_HEADPHONE; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++int open_output_mixed_bluetooth(long val) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed bluetooth. \n"); ++#endif ++ ++ return 0; ++} ++ ++ ++int open_output_mixed_louderspeaker_mixed(long val) ++{ ++ int ret; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open output mixed louderspeaker mixed. \n"); ++#endif ++ ++ /* set pcap output path register AR_EN=1, AL_EN=1 */ ++ if(MIXERISSTEREO) ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_R_L_STEREO); ++ else ++ SSP_PCAP_MONO_set(PCAP_MONO_PGA_RL); ++ e680boomer.path = BOOMER_IN_MONO_AND_STEREO_OUT_LOUDER_SPEAKER; ++ ++ codec_output_path = GET_OUTPUT_PATH(val); ++ codec_output_base = GET_OUTPUT_BASE(val); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AHS_CONFIG); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ARIGHT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_ALEFT_EN); ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_IN_SW); ++ ++ set_boomer_mode_control_reg(); ++ set_output_gain_hw_reg(); ++ ++ return ret; ++} ++ ++ ++void kernel_set_oscc_13m_clock(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "midi set oscc 13m clock \n" ); ++#endif ++ ++ if( DSPUSE13MCLK == 0 ) ++ OSCC |= 0x00000008; ++} ++ ++ ++void kernel_clr_oscc_13m_clock(void) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "midi clr oscc 13m clock \n"); ++#endif ++ ++ if( (DSPUSE13MCLK == 0 ) && (DSP16USE13MCLK == 0) ) /* for app will close midi after dsp16 opened under some cases */ ++ OSCC &= ~0x00000008; ++} ++ ++ ++void pcap_use_ap_13m_clock(void) ++{ ++ if( MIDIUSE13MCLK == 0 ) ++ OSCC |= 0x00000008; ++ set_GPIO_mode(AP_13MHZ_OUTPUT_PIN | GPIO_ALT_FN_3_OUT); ++ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_CLK_IN_SEL); ++} ++ ++ ++void pcap_use_bp_13m_clock(void) ++{ ++ if( MIDIUSE13MCLK == 0 ) ++ OSCC &= ~0x00000008; ++ set_GPIO_mode(AP_13MHZ_OUTPUT_PIN | GPIO_IN); ++ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CLK_IN_SEL); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_ST_DAC_ST_DAC_CLK_IN_SEL); ++} ++ ++ ++#ifdef CONFIG_PM ++int mixer_hw_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ switch(req){ ++ case PM_SUSPEND: ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " E680 boomer path = 0X%X before AP sleep. \n", e680boomer.path); ++#endif ++ if( (audioonflag & (PHONE_DEVICE|FM_DEVICE)) == 0 ){ ++ e680_boomer_path_tmp_shutdown(); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ } ++ break; ++ case PM_RESUME: ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " E680 after AP sleep.\n"); ++#endif ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_AUDIO_LOWPWR); ++ set_output_gain_hw_reg(); ++ if( gpio_flt_sel_status ) ++ Clear_Haptics_GPIO(); ++ else ++ Set_Haptics_GPIO(); ++ if(audioonflag) ++ (*mixer_open_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(codec_output_base|codec_output_path); ++ e680_boomer_path_restore(); ++ break; ++ } ++ return 0; ++} ++#endif ++ ++ ++void mute_output_to_avoid_pcap_noise(void) ++{ ++ e680_boomer_path_tmp_mono_lineout(); ++} ++ ++ ++void undo_mute_output_to_avoid_pcap_noise(void) ++{ ++ e680_boomer_path_restore(); ++} ++ ++ ++void Set_Haptics_GPIO(void) ++{ ++ e680_boomer_path_tmp_mono_lineout(); ++ ++ set_GPIO_mode(GPIO_FLT_SEL_BUL | GPIO_OUT); ++ clr_GPIO(GPIO_FLT_SEL_BUL); ++ PGSR(GPIO_FLT_SEL_BUL) &= ~GPIO_bit(GPIO_FLT_SEL_BUL); ++ gpio_flt_sel_status = 0; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " set haptics GPIO \n"); ++#endif ++ ++ e680_boomer_path_restore(); ++} ++ ++ ++void Clear_Haptics_GPIO(void) ++{ ++ e680_boomer_path_tmp_mono_lineout(); ++ ++ set_GPIO_mode(GPIO_FLT_SEL_BUL | GPIO_OUT); ++ set_GPIO(GPIO_FLT_SEL_BUL); ++ PGSR(GPIO_FLT_SEL_BUL) |= GPIO_bit(GPIO_FLT_SEL_BUL); ++ gpio_flt_sel_status = 1; ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG " clear haptics GPIO \n"); ++#endif ++ ++ e680_boomer_path_restore(); ++} ++ ++ ++#endif /* CONFIG_ARCH_EZX_E680 */ ++ ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-e680.h linux-2.6.16.5-exz/sound/oss/ezx-e680.h +--- linux-2.6.16.5/sound/oss/ezx-e680.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-e680.h 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,183 @@ ++/* ++ * linux/drivers/sound/ezx-e680.h ++ * ++ * ++ * Description: header file for ezx-e680.c ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * Jin Lihong(w20076) Jan 12,2004,LIBdd68327 Created,Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 close dsp protection,and add 3d control interface for app ++ * Jin Lihong(w20076) Apr.24,2004,LIBee03164 reduce music noise, add new pathes for haptics ++ * Jin Lihong(w20076) Jun.15,2004,LIBee21625 boomer's power management ++ * Jin Lihong(w20076) Jun.22,2004,LIBee24284 mixer power save ++ * Wu Hongxing(w20691)Jul.07,2004 LIBee29664 ap 13m clock usage. ++ * ++ */ ++ ++#ifndef EZX_E680_H ++#define EZX_E680_H ++ ++#include <linux/config.h> ++#include <linux/pm.h> ++ ++#ifdef CONFIG_PXA_EZX_E680 ++ ++//#define EZX_OSS_DEBUG /* debug switch for all ezx oss src files excluding ezx-audio.c */ ++#undef EZX_OSS_DEBUG ++//#define EZX_OSS_AUDIO_DEBUG /* debug switch for src file ezx-audio.c */ ++#undef EZX_OSS_AUDIO_DEBUG ++ ++/* ++#ifdef EZX_OSS_DBG ++#define OSSPRINTF(fmt,args...) printf(fmt,##args) ++#else ++#define OSSPRINTF(fmt,args...) { } ++#endif ++*/ ++ ++ ++#define MIXERISSTEREO ( audioonflag & (DSP_DEVICE|MIDI_DEVICE|FM_DEVICE) ) ++#define MIDIUSE13MCLK ( audioonflag & MIDI_DEVICE ) ++#define DSPUSE13MCLK ( audioonflag & DSP_DEVICE ) ++#define DSP16USE13MCLK ( audioonflag & DSP16_DEVICE ) ++ ++ ++typedef enum{ ++ PHONE_DEVICE = 0x01, ++ DSP_DEVICE = 0x02, ++ DSP16_DEVICE = 0x04, ++ AUDIO_DEVICE = 0x08, ++ MIDI_DEVICE = 0x10, ++ FM_DEVICE = 0x20 ++}audio_dev_type; ++ ++typedef enum{ ++ LOUDERSPEAKER_ON_HEADSET_ON_3D, ++ LOUDERSPEAKER_ON_HEADSET_OFF_3D, ++ LOUDERSPEAKER_OFF_HEADSET_ON_3D, ++ LOUDERSPEAKER_OFF_HEADSET_OFF_3D ++}boomer_3d_status; ++ ++ ++void e680_boomer_init(void); ++void e680_boomer_shutdown(void); ++void e680_boomer_path_mono_lineout(void); ++void e680_boomer_path_tmp_mono_lineout(void); ++void e680_boomer_path_tmp_shutdown(void); ++void e680_boomer_path_restore(void); ++ ++void poweron_mixer( audio_dev_type type ); ++void shutdown_mixer( audio_dev_type type ); ++void mixer_not_in_use(void); ++ ++void set_output_gain_hw_reg(void); ++void set_input_gain_hw_reg(void); ++ ++void set_boomer_3d_status(boomer_3d_status status); ++boomer_3d_status get_boomer_3d_status(void); ++ ++void set_gpio_va_sel_out_high(void); ++void set_gpio_va_sel_out_low(void); ++ ++void close_input_carkit(void); ++void close_input_handset(void); ++void close_input_headset(void); ++void close_input_funlight(void); ++ ++void open_input_carkit(void); ++void open_input_handset(void); ++void open_input_headset(void); ++void open_input_funlight(void); ++ ++void close_output_pcap_headset(void); ++void close_output_pcap_louderspeaker(void); ++void close_output_pcap_earpiece(void); ++void close_output_pcap_carkit(void); ++void close_output_pcap_headjack(void); ++void close_output_pcap_bluetooth(void); ++void close_output_pcap_louderspeaker_mixed(void); ++ ++void close_output_ma3_headset(void); ++void close_output_ma3_louderspeaker(void); ++void close_output_ma3_earpiece(void); ++void close_output_ma3_carkit(void); ++void close_output_ma3_headjack(void); ++void close_output_ma3_bluetooth(void); ++void close_output_ma3_louderspeaker_mixed(void); ++ ++void close_output_fm_headset(void); ++void close_output_fm_louderspeaker(void); ++void close_output_fm_earpiece(void); ++void close_output_fm_carkit(void); ++void close_output_fm_headjack(void); ++void close_output_fm_bluetooth(void); ++void close_output_fm_louderspeaker_mixed(void); ++ ++void close_output_mixed_headset(void); ++void close_output_mixed_louderspeaker(void); ++void close_output_mixed_earpiece(void); ++void close_output_mixed_carkit(void); ++void close_output_mixed_headjack(void); ++void close_output_mixed_bluetooth(void); ++void close_output_mixed_louderspeaker_mixed(void); ++ ++int open_output_pcap_headset(long val); ++int open_output_pcap_louderspeaker(long val); ++int open_output_pcap_earpiece(long val); ++int open_output_pcap_carkit(long val); ++int open_output_pcap_headjack(long val); ++int open_output_pcap_bluetooth(long val); ++int open_output_pcap_louderspeaker_mixed(long val); ++ ++int open_output_ma3_headset(long val); ++int open_output_ma3_louderspeaker(long val); ++int open_output_ma3_earpiece(long val); ++int open_output_ma3_carkit(long val); ++int open_output_ma3_headjack(long val); ++int open_output_ma3_bluetooth(long val); ++int open_output_ma3_louderspeaker_mixed(long val); ++ ++int open_output_fm_headset(long val); ++int open_output_fm_louderspeaker(long val); ++int open_output_fm_earpiece(long val); ++int open_output_fm_carkit(long val); ++int open_output_fm_headjack(long val); ++int open_output_fm_bluetooth(long val); ++int open_output_fm_louderspeaker_mixed(long val); ++ ++int open_output_mixed_headset(long val); ++int open_output_mixed_louderspeaker(long val); ++int open_output_mixed_earpiece(long val); ++int open_output_mixed_carkit(long val); ++int open_output_mixed_headjack(long val); ++int open_output_mixed_bluetooth(long val); ++int open_output_mixed_louderspeaker_mixed(long val); ++ ++void kernel_set_oscc_13m_clock(void); ++void kernel_clr_oscc_13m_clock(void); ++void pcap_use_ap_13m_clock(void); ++void pcap_use_bp_13m_clock(void); ++ ++int mixer_hw_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data); ++void mute_output_to_avoid_pcap_noise(void); ++void undo_mute_output_to_avoid_pcap_noise(void); ++ ++void Set_Haptics_GPIO(void); ++void Clear_Haptics_GPIO(void); ++ ++ ++#endif /* CONFIG_ARCH_EZX_E680 */ ++ ++ ++#endif ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-nssp.c linux-2.6.16.5-exz/sound/oss/ezx-nssp.c +--- linux-2.6.16.5/sound/oss/ezx-nssp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-nssp.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,358 @@ ++/* ++ * linux/drivers/sound/ezx-nssp.c ++ * ++ * ++ * Description: nssp interface for the ezx platform ++ * ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhouqiong, Motorola Jun 20,2002 created ++ * zhouqiong, Motorola Sep 19,2002 according code review meeting minutes. ++ * zhouqiong, Motorola Oct 30,2002 according new requirement for VA. ++ * zhouqiong, Motorola Nov 05,2002 according code review meeting minutes. ++ * zhouqiong, Motorola Mar 04,2003 (1) don't close headset interrupt; ++ * (2) when headset in, output gain decrease 6db ++ * LiYong, Motorola Sep 23,2003 (1)Port from EZX; (2)Modify the NSSP port inital ++ * Jin Lihong(w20076), Motorola Jan 02,2004 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076),Motorola Feb.23,2004,LIBdd79747 add e680 audio path switch and gain setting funcs ++ * Jin Lihong(w20076),Motorola Mar.15,2004,LIBdd86574 mixer bug fix ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/poll.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-audio.h" ++#include "ezx-common.h" ++ ++ ++static DECLARE_MUTEX(cotulla_nssp_mutex); ++ ++static int nssp_init(void); ++static void nssp_shutdown(void); ++ ++ ++/*initialize hardware, nssp controller and pcap register*/ ++static int nssp_init(void) ++{ ++ unsigned long flags; ++ unsigned long ssp_pcap_register_val; ++ unsigned int ssp_pcap_bit_status; ++ volatile unsigned long audiostatus; ++ unsigned long timeout; ++ ++ down(&cotulla_nssp_mutex); ++ ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++ if( MONODEVOPENED == 0 ) ++ pcap_use_ap_13m_clock(); ++ audioonflag |= AUDIO_DEVICE; ++ ++#ifdef EZX_OSS_DEBUG ++ printk("setup nssp controller register \n"); ++#endif ++ local_irq_save(flags); ++ CKEN |= CKEN3_NSSP; /* need enable cken3 */ ++ ++ set_GPIO_mode(GPIO_BITCLK_IN_NSSP_MD); /* BitCLK */ ++ set_GPIO_mode(GPIO_SYNC_IN_NSSP_MD); /* FS */ ++ /*At E680,the NSSP TX and RX pins are single direction */ ++// set_GPIO_mode(GPIO_SDATA_OUT_NSSP_MD); /* TXD ssp2 ALF out 2 */ ++ set_GPIO_mode(GPIO_SDATA_IN_NSSP_MD); /* RXD ssp2 ALF in 1*/ ++ /* setup nssp port */ ++ NSSCR0 = NSSCR0_FRF_PSP | NSSCR0_DSS_16bit; /* PSP mode, 16bit */ ++ NSSCR1 = NSSCR1_TTE | NSSCR1_EBCEI | NSSCR1_SCLKDIR | NSSCR1_SFRMDIR | NSSCR1_TFTH_4 | NSSCR1_RFTH_14; ++ NSSPSP = NSSPSP_SFRMWDTH_1 | NSSPSP_STRTDLY_1 | NSSPSP_SFRMP_HIGH | NSSPSP_SCMODE; ++ NSSCR1 |= NSSCR1_TSRE | NSSCR1_RSRE; /* enable dma request */ ++ NSSCR0 |= NSSCR0_SSE; /* enable nssp controller */ ++ local_irq_restore(flags); ++ ++#ifdef EZX_OSS_DEBUG ++ audiostatus = NSSCR0; ++ printk("NSSCR0 = 0x%lx\n", audiostatus); ++ audiostatus = NSSCR1; ++ printk("NSSCR1 = 0x%lx\n", audiostatus); ++ audiostatus = NSSPSP; ++ printk("NSSPSP = 0x%lx\n", audiostatus); ++#endif ++ ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(0x0d,&ssp_pcap_register_val); ++ printk("pcap register 13 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0c,&ssp_pcap_register_val); ++ printk("pcap register 12 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0b,&ssp_pcap_register_val); ++ printk("pcap register 11 = 0x%lx\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x1a,&ssp_pcap_register_val); ++ printk("pcap register 26 = 0x%lx\n", ssp_pcap_register_val); ++#endif ++ ++ timeout = 0; ++ /* check if ssp is ready for slave operation */ ++ while(((audiostatus = NSSSR) & NSSSR_CSS) !=0){ ++ if((timeout++) > 10000000) ++ goto err; ++ } ++#ifdef EZX_OSS_DEBUG ++ printk(" complete all hardware init \n"); ++#endif ++ up(&cotulla_nssp_mutex); ++ return 0; ++ ++err: ++ up(&cotulla_nssp_mutex); ++ printk("audio panic: ssp don't ready for slave operation!!! "); ++ return -ENODEV; ++} ++ ++ ++static void nssp_shutdown(void) ++{ ++ down(&cotulla_nssp_mutex); ++ ++ audioonflag &= ~AUDIO_DEVICE; ++ if( MONODEVOPENED == 0 ) ++ pcap_use_bp_13m_clock(); ++ ++#ifdef EZX_OSS_DEBUG ++ printk("close nssp port\n"); ++#endif ++ NSSCR0 = 0; ++ NSSCR1 = 0; ++ NSSPSP = 0; ++ CKEN &= ~CKEN3_NSSP; /* SSP2 need control the CKEN3 */ ++ ++ set_GPIO_mode(GPIO_NSSP_SCLK2 | GPIO_IN); /* BitCLK */ ++ set_GPIO_mode(GPIO_NSSP_SFRM2 | GPIO_IN); /* FS */ ++ set_GPIO_mode(GPIO_NSSP_TXD2 | GPIO_IN); ++ set_GPIO_mode(GPIO_NSSP_RXD2 | GPIO_IN); ++ ++#ifdef EZX_OSS_DEBUG ++ printk("close pcap register\n"); ++#endif ++ ++ up(&cotulla_nssp_mutex); ++} ++ ++ ++/* ++ * nssp codec ioctls ++ */ ++static int codec_adc_rate = PHONE_CODEC_DEFAULT_RATE; /* default 8k sample rate */ ++static int codec_dac_rate = PHONE_CODEC_DEFAULT_RATE; /* default 8k sample rate */ ++ ++static int nssp_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret; ++ long val; ++ int audiostatus, timeout; ++ ++ switch(cmd) { ++ case SNDCTL_DSP_STEREO: ++#ifdef EZX_OSS_DEBUG ++ printk(" check if support stereo\n"); ++#endif ++ ret = get_user(val, (int *) arg); ++ if (ret) ++ return ret; ++ if(val) /* not support stereo mode */ ++ ret = -EINVAL; ++ else ++ ret = 1; ++ return put_user(ret, (int *) arg); ++ ++ case SNDCTL_DSP_CHANNELS: ++ case SOUND_PCM_READ_CHANNELS: ++#ifdef EZX_OSS_DEBUG ++ printk(" check if 2 channels \n"); ++#endif ++ return put_user(1, (long *) arg); ++ ++ case SNDCTL_DSP_SPEED: ++#ifdef EZX_OSS_DEBUG ++ printk(" set sample frequency \n"); ++#endif ++ ret = get_user(val, (long *) arg); ++ if (ret) ++ return ret; ++ ++ down(&cotulla_nssp_mutex); ++ NSSCR0 &= ~NSSCR0_SSE; ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ switch(val) ++ { ++ case PHONE_CODEC_16K_RATE: /*16K sample rate */ ++ ret = SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); ++ codec_adc_rate = val; ++ codec_dac_rate = val; ++ break; ++ case PHONE_CODEC_DEFAULT_RATE: /*8K sample rate */ ++ ret = SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_FS_8K_16K); ++ codec_adc_rate = val; ++ codec_dac_rate = val; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ /* reset digital filter(DF_RESET=1) */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_DF_RESET); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ ++ NSSCR0 |= NSSCR0_SSE; /* enable nssp controller */ ++ timeout = 0; ++ /* check if ssp is ready for slave operation */ ++ while(((audiostatus = NSSSR) & NSSSR_CSS) !=0) ++ { ++ if((timeout++) > 10000000) ++ { ++ printk("audio panic: can't be slave mode!!!"); ++ ret =-ENODEV; ++ break; ++ } ++ } ++ up(&cotulla_nssp_mutex); ++#ifdef EZX_OSS_DEBUG ++ printk("AD sample freq = %d\n", codec_adc_rate); ++ printk("DA sample freq = %d\n", codec_dac_rate); ++#endif ++ return put_user(codec_adc_rate, (long *) arg); ++ ++ case SOUND_PCM_READ_RATE: ++ if (file->f_mode & FMODE_WRITE) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk("read DA sample freq\n"); ++#endif ++ val = codec_dac_rate; ++ } ++ if (file->f_mode & FMODE_READ) ++ { ++#ifdef EZX_OSS_DEBUG ++ printk("read AD sample freq\n"); ++#endif ++ val = codec_adc_rate; ++ } ++ return put_user(val, (long *) arg); ++ ++ case SNDCTL_DSP_SETFMT: ++ case SNDCTL_DSP_GETFMTS: ++ /* SUPPORT little endian signed 16 */ ++#ifdef EZX_OSS_DEBUG ++ printk("data format is AFMT_S16_LEd\n"); ++#endif ++ return put_user(AFMT_S16_LE, (long *) arg); ++ ++ default: ++ return mixer_ioctl(inode, file, cmd, arg); ++ } ++ return 0; ++} ++ ++ ++/* ++ * Audio stuff ++ */ ++ ++static audio_stream_t nssp_audio_out = { ++ name: "nssp audio out", ++ dcmd: DCMD_TXNSSDR, ++ drcmr: &DRCMRTXNSSDR, /* nssp dma map register */ ++ dev_addr: __PREG(NSSDR), ++}; ++ ++static audio_stream_t nssp_audio_in = { ++ name: "nssp audio in", ++ dcmd: DCMD_RXNSSDR, ++ drcmr: &DRCMRRXNSSDR, /* nssp dma map register */ ++ dev_addr: __PREG(NSSDR), ++}; ++ ++static audio_state_t nssp_audio_state = { ++ output_stream: &nssp_audio_out, ++ input_stream: &nssp_audio_in, ++ client_ioctl: nssp_ioctl, ++ hw_init: nssp_init, ++ hw_shutdown: nssp_shutdown, ++ sem: __MUTEX_INITIALIZER(nssp_audio_state.sem), ++}; ++ ++ ++static int nssp_audio_open(struct inode *inode, struct file *file) ++{ ++#ifdef EZX_OSS_DEBUG ++ printk("nssp audio open \n"); ++#endif ++ return cotulla_audio_attach(inode, file, &nssp_audio_state); ++} ++ ++ ++/* ++ * Missing fields of this structure will be patched with the call ++ * to cotulla_audio_attach(). ++ */ ++ ++ ++static struct file_operations nssp_audio_fops = { ++ open: nssp_audio_open, ++ owner: THIS_MODULE ++}; ++ ++ ++static int __init cotulla_nssp_init(void) ++{ ++ nssp_audio_state.dev_dsp = register_sound_audio(&nssp_audio_fops, -1); ++ ++ set_GPIO_mode(GPIO_NSSP_SCLK2 | GPIO_IN); /* BitCLK */ ++ set_GPIO_mode(GPIO_NSSP_SFRM2 | GPIO_IN); /* FS */ ++ set_GPIO_mode(GPIO_NSSP_TXD2 | GPIO_IN); ++ set_GPIO_mode(GPIO_NSSP_RXD2 | GPIO_IN); /* RXD ssp2 ALF in 1*/ ++ ++#ifdef EZX_OSS_DEBUG ++ printk("cotulla-nssp-init ok\n"); ++#endif ++ return 0; ++} ++ ++ ++static void __exit cotulla_nssp_exit(void) ++{ ++ unregister_sound_audio(nssp_audio_state.dev_dsp); ++#ifdef EZX_OSS_DEBUG ++ printk("cotulla-nssp-exit ok\n"); ++#endif ++} ++ ++ ++module_init(cotulla_nssp_init); ++module_exit(cotulla_nssp_exit); ++ ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-phone.c linux-2.6.16.5-exz/sound/oss/ezx-phone.c +--- linux-2.6.16.5/sound/oss/ezx-phone.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-phone.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,280 @@ ++/* ++ * linux/drivers/sound/ezx-phone ++ * ++ * ++ * Description: phone interface for EZX. for application can't direct call interface in kernel space from ++ * user space.so phone controll realize a char device. ++ * ++ * ++ * copyright: Motorola ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhouqiong Aug 02,2002 created ++ * zhouqiong Mar 03,2003 (1) don't close headset interrupt; ++ * (2) move bluetooth to phone device ioctl ++ * LiYong Sep 23,2003 Port from EZX ++ * Jin Lihong(w20076) Jan 02,2004,LIBdd66088 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076) Jan 13,2004,LIBdd68327 Make the e680 louder speaker work. ++ * Jin Lihong(w20076) Mar.15,2004,LIBdd86574 mixer bug fix ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90336 play music noise tmp solution ++ * Jin Lihong(w20076) Mar.25,2004,LIBdd90846 a780 new gain setting interface ++ * Jin Lihong(w20076) Apr.20,2004,LIBee01165 va of a phone call for e680 ++ * Jin Lihong(w20076) Apr.24,2004,LIBee03164 a780 bitclock restore to normal because pcap2 upgraded ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/delay.h> ++#include <linux/fs.h> ++#include <linux/major.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "ezx-common.h" ++ ++ ++#ifdef CONFIG_PM ++static struct pm_dev *pm_dev; ++#endif ++ ++static DECLARE_MUTEX(phone_mutex); ++ ++#ifdef CONFIG_PM ++#ifdef CONFIG_ARCH_EZX_E680 ++extern u32 gpio_va_sel_status; ++#endif ++ ++ ++static int phone_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ switch(req) ++ { ++ case PM_SUSPEND: ++ break; ++ case PM_RESUME: ++#ifdef CONFIG_ARCH_EZX_E680 ++ set_GPIO_mode(GPIO_VA_SEL_BUL | GPIO_OUT); ++ if(gpio_va_sel_status) ++ { ++ set_GPIO(GPIO_VA_SEL_BUL); ++ } ++ else ++ { ++ clr_GPIO(GPIO_VA_SEL_BUL); ++ } ++#endif ++ break; ++ } ++ return 0; ++} ++#endif ++ ++ ++void bluetoothaudio_open(void) ++{} ++void bluetoothaudio_close(void) ++{} ++ ++static int phone_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ unsigned long ssp_pcap_register_val; ++ ++ switch(cmd) { ++ case BLUETOOTH_AUDIO_ON: ++#ifdef EZX_OSS_DEBUG ++ printk("bluetooth audio on\n"); ++#endif ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(SSP_PCAP_ADJ_AUD_CODEC_REGISTER, &ssp_pcap_register_val); ++ printk("AUD_CODEC=0x%x\n", ssp_pcap_register_val); ++#endif ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); ++ (*mixer_close_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(); ++ break; ++ ++ case BLUETOOTH_AUDIO_OFF: ++#ifdef EZX_OSS_DEBUG ++ printk("bluetooth audio off\n"); ++#endif ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(SSP_PCAP_ADJ_AUD_CODEC_REGISTER, &ssp_pcap_register_val); ++ printk("AUD_CODEC=0x%x\n", ssp_pcap_register_val); ++#endif ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_R_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_PGA_L_EN); ++ (*mixer_open_output_path[OUTPUT_BASE_TYPE(codec_output_base)][codec_output_path])(codec_output_base|codec_output_path ); ++ break; ++ ++ default: ++ return mixer_ioctl(inode, file, cmd, arg); ++ } ++ return 0; ++} ++ ++ ++/* ++ * there is a supposition: ++ * when run phone_open, other audio device is stopped, pcap is free ++ */ ++static int count = 0; ++static int phone_open(struct inode *inode, struct file *file) ++{ ++ unsigned int ssp_pcap_register_val; ++ ++/* ++#ifdef CONFIG_ARCH_EZX_E680 ++ if( audioonflag & FM_DEVICE ){ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "E680 open phone EBUSY because 0x%X device is using the sound hardware.\n",audioonflag ); ++#endif ++ return -EBUSY; ++ } ++#endif ++*/ ++ ++ if(!count){ ++ count ++; ++ ++ down(&phone_mutex); ++ ++ mute_output_to_avoid_pcap_noise(); ++ audioonflag |= PHONE_DEVICE; ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++ pcap_use_bp_13m_clock(); ++ ++ ++#ifdef EZX_OSS_DEBUG ++ printk(EZXOSS_DEBUG "open phone device, init pcap register\n"); ++#endif ++ set_pcap_telephone_codec(0); ++ set_pcap_output_path(); ++ set_pcap_input_path(); ++ ++ undo_mute_output_to_avoid_pcap_noise(); ++ ++#ifdef EZX_OSS_DEBUG ++ SSP_PCAP_read_data_from_PCAP(0x0b, &ssp_pcap_register_val); ++ printk("reg 11=0x%x\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0d, &ssp_pcap_register_val); ++ printk("reg 13=0x%x\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x0c, &ssp_pcap_register_val); ++ printk("reg 12=0x%x\n", ssp_pcap_register_val); ++ SSP_PCAP_read_data_from_PCAP(0x1a, &ssp_pcap_register_val); ++ printk("reg 26=0x%x\n", ssp_pcap_register_val); ++#endif ++ up(&phone_mutex); ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ set_gpio_va_sel_out_low(); ++#endif ++ ++#ifdef CONFIG_PM ++ pm_dev = pm_register(PM_SYS_DEV, 0, phone_pm_callback); ++#endif ++ return 0; ++ } ++ else ++ return -EBUSY; ++} ++ ++ ++static int phone_release(struct inode *inode, struct file *file) ++{ ++ count --; ++ if(!count){ ++ down(&phone_mutex); ++ ++ mute_output_to_avoid_pcap_noise(); ++ ++ /* close pcap input path */ ++ if(micinflag) ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_TX_AUD_AMPS_REGISTER,SSP_PCAP_ADJ_BIT_TX_AUD_AMPS_MB_ON2); ++ else ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_TX_AUD_AMPS_REGISTER, 0); ++ /* close pcap output path */ ++ SSP_PCAP_write_data_to_PCAP(SSP_PCAP_ADJ_AUD_RX_AMPS_REGISTER,SSP_PCAP_ADJ_BIT_AUD_RX_AMPS_A1CTRL); ++ /* disable PCAP mono codec */ ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_CLK_EN); ++ SSP_PCAP_bit_clean(SSP_PCAP_ADJ_BIT_AUD_CODEC_CDC_EN); ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_SMB); ++ ++ /* set fsync, tx, bitclk are tri-stated */ ++ SSP_PCAP_bit_set(SSP_PCAP_ADJ_BIT_AUD_CODEC_CD_TS); ++ ++ up(&phone_mutex); ++ ++#ifdef CONFIG_ARCH_EZX_E680 ++ set_gpio_va_sel_out_high(); ++ e680_boomer_path_mono_lineout(); /* mute hw noise and save power for e680 */ ++#endif ++ ++ pcap_use_bp_13m_clock(); ++ audioonflag &= ~PHONE_DEVICE; ++ ++#ifdef CONFIG_PM ++ pm_unregister(pm_dev); ++#endif ++ } ++ ++ return 0; ++} ++ ++ ++static struct file_operations device_fops = { ++ owner: THIS_MODULE, ++ open: phone_open, ++ release: phone_release, ++ ioctl: phone_ioctl, ++}; ++ ++static int __init phone_init(void) ++{ ++ int ret; ++ ret = register_chrdev(MYPHONE_MAJOR,"phone", &device_fops); ++ if(ret) ++ { ++ printk("can't register phone device with kernel"); ++ } ++#ifdef EZX_OSS_DEBUG ++ printk("register phone device with kernel ok \n"); ++#endif ++ return 0; ++} ++ ++static void __exit phone_exit(void) ++{ ++ unregister_chrdev(MYPHONE_MAJOR, "phone"); ++#ifdef EZX_OSS_DEBUG ++ printk("unregister phone device \n"); ++#endif ++} ++ ++ ++module_init(phone_init); ++module_exit(phone_exit); ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-vibrator.c linux-2.6.16.5-exz/sound/oss/ezx-vibrator.c +--- linux-2.6.16.5/sound/oss/ezx-vibrator.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-vibrator.c 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,245 @@ ++/* ++ * linux/drivers/sound/vibrator.c ++ * ++ * ++ * Description: vibrator interface for EZX. for application can't direct call interface in kernel space from ++ * user space.so vibrator still realize a char device. ++ * ++ * ++ * (c) Copyright Motorola 2003, All rights reserved. ++ * ++ * ++ * History: ++ * zhouqiong Jun 20,2002 created ++ * Kin Wong Nov 05,2003 Renamed ezx-vibrator.h to vibrator.h ++ * Jin Lihong(w20076) Jan 02,2004 (1) Port from UDC e680 kernel of jem vob. ++ * (2) Move audio driver DEBUG macro definition to ezx-audio.h ++ * header file,and redefine DEBUG to EZX_OSS_DEBUG ++ * (3) reorganize file header ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 reorganise file header ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/pci.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/fs.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/uaccess.h> ++#include <asm/semaphore.h> ++#include <asm/dma.h> ++ ++#include "../misc/ssp_pcap.h" ++#include "ezx-vibrator.h" ++ ++ ++#ifdef CONFIG_PM ++static struct pm_dev *pm_dev; ++#endif ++ ++static int active=0; ++static int voltage=0; ++ ++static int vibrator_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret; ++ long val; ++ ++ switch(cmd) ++ { ++ case VIBRATOR_ENABLE: ++#ifdef EZX_OSS_DEBUG ++ printk("enable vibrator \n"); ++#endif ++ ret = get_user(val, (int *) arg); ++ if (ret) ++ return ret; ++ switch(val) ++ { ++ case 0: ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator level 0 \n"); ++#endif ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL0); ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL0); ++ active = 1; ++ voltage = 0; ++ SSP_vibrate_start_command(); ++ break; ++ case 1: ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator level 1 \n"); ++#endif ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL1); ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL1); ++ active = 1; ++ voltage = 1; ++ SSP_vibrate_start_command(); ++ break; ++ case 2: ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator level 2 \n"); ++#endif ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL2); ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL2); ++ active = 1; ++ voltage = 2; ++ SSP_vibrate_start_command(); ++ break; ++ case 3: ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator level 3 \n"); ++#endif ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3); ++ ret = SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3); ++ active = 1; ++ voltage = 3; ++ SSP_vibrate_start_command(); ++ break; ++ default: ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator level error \n"); ++#endif ++ return -EINVAL; ++ } ++ return put_user(ret, (int *) arg); ++ ++ case VIBRATOR_DISABLE: ++#ifdef EZX_OSS_DEBUG ++ printk("disable vibrator \n"); ++#endif ++ ret = 0; ++ active = 0; ++ SSP_vibrate_stop_command(); ++ return put_user(ret, (int *) arg); ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int vibrator_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ switch(req) ++ { ++ case PM_SUSPEND: ++ if(active) ++ { ++ SSP_vibrate_stop_command(); ++ } ++ break; ++ case PM_RESUME: ++ if(active) ++ { ++ switch(voltage) ++ { ++ case 0: ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL0); ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL0); ++ break; ++ case 1: ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL1); ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL1); ++ break; ++ case 2: ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL2); ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL2); ++ break; ++ case 3: ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3); ++ SSP_PCAP_V_VIB_level_set(PCAP_VIBRATOR_VOLTAGE_LEVEL3); ++ break; ++ default: ++ break; ++ } ++ SSP_vibrate_start_command(); ++ } ++ break; ++ } ++ return 0; ++} ++#endif ++ ++static int count=0; ++static int vibrator_open(struct inode *inode, struct file *file) ++{ ++ if(!count) ++ { ++ count ++; ++ //ssp_pcap_init(); ++ ssp_pcap_open(SSP_PCAP_AUDIO_OPEN); ++#ifdef CONFIG_PM ++ pm_dev = pm_register(PM_SYS_DEV, 0, vibrator_pm_callback); ++#endif ++#ifdef EZX_OSS_DEBUG ++ printk("open vibrator \n"); ++#endif ++ return 0; ++ } ++ else ++ return -EBUSY; ++} ++ ++static int vibrator_release(struct inode *inode, struct file *file) ++{ ++ count --; ++ if(!count) ++ { ++#ifdef CONFIG_PM ++ pm_unregister(pm_dev); ++#endif ++#ifdef EZX_OSS_DEBUG ++ printk("close vibrator \n"); ++#endif ++ } ++ return 0; ++} ++ ++ ++static struct file_operations device_fops = { ++ owner: THIS_MODULE, ++ open: vibrator_open, ++ release: vibrator_release, ++ ioctl: vibrator_ioctl, ++}; ++ ++static int __init vibrator_init(void) ++{ ++ int ret; ++#ifdef EZX_OSS_DEBUG ++ printk("enter vibrator init...\n"); ++#endif ++ ret = register_chrdev(VIBRATOR_MAJOR,"vibrator", &device_fops); ++ if(ret){ ++ printk("can't register vibrator device with kernel"); ++ } ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator init ok\n"); ++#endif ++ return 0; ++} ++ ++static void __exit vibrator_exit(void) ++{ ++ unregister_chrdev(VIBRATOR_MAJOR, "vibrator"); ++#ifdef EZX_OSS_DEBUG ++ printk("vibrator exit ok\n"); ++#endif ++ return; ++} ++ ++ ++module_init(vibrator_init); ++module_exit(vibrator_exit); ++ ++ +diff -Nru --exclude-from=/sunbeam/home/laforge/scripts/dontdiff linux-2.6.16.5/sound/oss/ezx-vibrator.h linux-2.6.16.5-exz/sound/oss/ezx-vibrator.h +--- linux-2.6.16.5/sound/oss/ezx-vibrator.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.5-exz/sound/oss/ezx-vibrator.h 2006-04-16 18:49:29.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* ++ * linux/drivers/sound/ezx-vibrator.h ++ * ++ * Copyright: BJDC motorola. ++ * ++ * This program 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. ++ * ++ * ++ * History: ++ * zhouqiong Jun 20,2002 created ++ * Jin Lihong(w20076) Jan 02,2004 (1) Port from UDC e680 kernel of jem vob. ++ * (2) reorganize file header ++ * Jin Lihong(w20076) Apr.13,2004,LIBdd96876 reorganise file header ++ * ++ */ ++ ++#ifndef EZX_VIBRATOR_H ++#define EZX_VIBRATOR_H ++ ++#include <linux/ioctl.h> ++ ++ ++#define VIBRATOR_MAJOR 108 ++#define VIBRATOR_IOCTL_BASE 0xbb ++#define VIBRATOR_ENABLE _IOW (VIBRATOR_IOCTL_BASE,1,int) ++#define VIBRATOR_DISABLE _IO (VIBRATOR_IOCTL_BASE,2) ++ ++ ++#endif ++ ++ |