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