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
+
+