| /**************************************************************************** |
| Copyright 2009 - 2012 Broadcom Corporation |
| Unless you and Broadcom execute a separate written software license agreement |
| governing use of this software, this software is licensed to you under the |
| terms of the GNU General Public License version 2 (the GPL), available at |
| http://www.broadcom.com/licenses/GPLv2.php |
| |
| with the following added to such license: |
| As a special exception, the copyright holders of this software give you |
| permission to link this software with independent modules, and to copy and |
| distribute the resulting executable under terms of your choice, provided |
| that you also meet, for each linked independent module, the terms and |
| conditions of the license of that module. |
| An independent module is a module which is not derived from this software. |
| The special exception does not apply to any modifications of the software. |
| Notwithstanding the above, under no circumstances may you combine this software |
| in any way with any other Broadcom software provided under a license other than |
| the GPL, without Broadcom's express prior written consent. |
| ***************************************************************************/ |
| /** |
| * |
| * @file audio_vdriver.c |
| * @brief Audio VDriver API for CAPH |
| * |
| ******************************************************************************/ |
| |
| /*============================================================================= |
| // Include directives |
| //============================================================================= |
| */ |
| #include <linux/kernel.h> |
| #include <linux/slab.h> |
| #include <linux/completion.h> |
| #include <linux/jiffies.h> |
| #include "mobcom_types.h" |
| #include "audio_consts.h" |
| |
| #include "csl_apcmd.h" |
| |
| #include "bcm_fuse_sysparm_CIB.h" |
| |
| #include "csl_caph.h" |
| #include "csl_dsp.h" |
| #include "csl_caph_audioh.h" |
| #include "resultcode.h" |
| #include "csl_caph_hwctrl.h" |
| #include "audio_vdriver.h" |
| #include "audio_rpc.h" |
| #include <mach/comms/platform_mconfig.h> |
| #include "io.h" |
| #include "csl_dsp_cneon_api.h" |
| #if defined(ENABLE_DMA_VOICE) |
| #include "csl_dsp_caph_control_api.h" |
| #endif |
| |
| #include "audio_controller.h" |
| #include "audio_ddriver.h" |
| #include "audio_trace.h" |
| |
| #include "taskmsgs.h" |
| #include "ipcproperties.h" |
| |
| #include "rpc_global.h" |
| #include "rpc_ipc.h" |
| #include "xdr_porting_layer.h" |
| #include "xdr.h" |
| #include "rpc_api.h" |
| |
| /** |
| * |
| * @addtogroup AudioDriverGroup |
| * @{ |
| */ |
| |
| /*============================================================================= |
| // Private Type and Constant declarations |
| //============================================================================= |
| */ |
| |
| typedef void (*AUDDRV_User_CB) (UInt32 param1, UInt32 param2, UInt32 param3); |
| |
| struct _AUDDRV_PathID_t { |
| CSL_CAPH_PathID ulPathID; |
| CSL_CAPH_PathID ul2PathID; |
| CSL_CAPH_PathID dlPathID; |
| }; |
| #define AUDDRV_PathID_t struct _AUDDRV_PathID_t |
| |
| /*============================================================================= |
| // Private Variable declarations |
| //============================================================================= |
| */ |
| #if defined(CONFIG_BCM_MODEM) |
| #define AUDIO_MODEM(a) a |
| #else |
| #define AUDIO_MODEM(a) |
| #endif |
| |
| /*this is needed because DSPCMD_AUDIO_ENABLE sets/clears AMCR. |
| AUDEN for both voiceIn and voiceOut */ |
| static Boolean voicePlayOutpathEnabled = FALSE; |
| |
| static AUDDRV_PathID_t telephonyPathID; |
| #if defined(CONFIG_RHEA_PANDA) |
| CSL_CAPH_PathID dlExtModemPathID, ulExtModemPathID; |
| #endif |
| |
| static void *sUserCB; |
| static CSL_CAPH_DEVICE_e sink = CSL_CAPH_DEV_NONE; |
| static Boolean userEQOn = FALSE; |
| /* If TRUE, bypass EQ filter setting request from audio controller.*/ |
| |
| /* used in pcm i/f control. assume one mic, one spkr. */ |
| static AUDIO_SOURCE_Enum_t currVoiceMic = AUDIO_SOURCE_UNDEFINED; |
| static AUDIO_SINK_Enum_t currVoiceSpkr = AUDIO_SINK_UNDEFINED; |
| |
| |
| static Boolean dspECEnable = TRUE; |
| static Boolean dspNSEnable = TRUE; |
| static Boolean controlFlagForCustomGain = FALSE; |
| static Boolean inCallRateChange = FALSE; |
| static int audio_tuning_flag; |
| static Boolean voiceRecOn = FALSE; |
| static AUDIO_SOURCE_Enum_t voiceInMic; |
| static AUDIO_SAMPLING_RATE_t voiceInSr; |
| |
| struct _Audio_Driver_t { |
| UInt8 isRunning; |
| UInt32 taskID; |
| }; |
| #define Audio_Driver_t struct _Audio_Driver_t |
| |
| static Audio_Driver_t sAudDrv = { 0 }; |
| |
| static audio_codecId_handler_t codecId_handler; |
| static audio_handleCPReset_handler_t cpReset_handler; |
| static Int32 curCallMode = CALL_MODE_NONE; |
| |
| struct completion audioEnableDone; |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| #define AUDIO_ENABLE_RESP_TIMEOUT 50 /* 50ms */ |
| #define timeout_jiff msecs_to_jiffies(AUDIO_ENABLE_RESP_TIMEOUT) |
| |
| struct completion extModemCallDone; |
| #endif |
| |
| /*============================================================================= |
| // Private function prototypes |
| //============================================================================= |
| */ |
| #ifndef CONFIG_BCM_MODEM |
| /* this array initializes the system parameters with the values |
| from param_audio_rhea.txt for different modes(mic_pga - hw_sidetone_gain)*/ |
| static AudioSysParm_t audio_parm_table[AUDIO_MODE_NUMBER_VOICE] = { |
| {72, 36, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 1, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 65520, |
| 65520, 1, 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 16, 16, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 65520, |
| 65520, 0, 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 16, 16, 0, |
| 1, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 65520, |
| 65520, 1, 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 8, 8, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 65520, |
| 65520, 0, 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} }, |
| {72, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 96, 0, 0, 0, 0, |
| 0, {0} } |
| }; |
| #endif |
| |
| #ifdef CONFIG_BCM_MODEM |
| SysAudioParm_t *AudParmP(void) |
| #else |
| AudioSysParm_t *AudParmP(void) |
| #endif |
| { |
| #if defined(BSP_ONLY_BUILD) |
| return NULL; |
| #elif defined(CONFIG_BCM_MODEM) |
| return APSYSPARM_GetAudioParmAccessPtr(); |
| #else |
| return &audio_parm_table[0]; |
| #endif |
| } |
| |
| static UInt32 *AUDIO_GetIHF48KHzBufferBaseAddress(void); |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| static void AUDDRV_ExtModem_Telephony_Init(AUDIO_SOURCE_Enum_t mic, |
| AUDIO_SINK_Enum_t speaker, |
| AudioMode_t mode, AudioApp_t app, |
| int bDualMic_IsNeeded, |
| int bmuteVoiceCall); |
| static void AUDDRV_ExtModem_Telephony_Deinit(void); |
| static void AP_ProcessExtModemCallDone(UInt16 enabled_path); |
| #endif |
| static void AUDDRV_Telephony_InitHW(AUDIO_SOURCE_Enum_t mic, |
| AUDIO_SINK_Enum_t speaker, |
| AUDIO_SAMPLING_RATE_t sample_rate, |
| Boolean bNeedDualMic); |
| |
| static void AUDDRV_Telephony_DeinitHW(void); |
| static CSL_CAPH_DEVICE_e AUDDRV_GetDRVDeviceFromSpkr(AUDIO_SINK_Enum_t spkr); |
| static CSL_CAPH_DEVICE_e AUDDRV_GetDRVDeviceFromMic(AUDIO_SOURCE_Enum_t mic); |
| |
| static void AUDDRV_HW_SetFilter(AUDDRV_HWCTRL_FILTER_e filter, |
| void *coeff); |
| static void AUDDRV_HW_EnableSideTone(AudioMode_t audio_mode); |
| static void AUDDRV_HW_DisableSideTone(AudioMode_t audio_mode); |
| static void AP_ProcessAudioEnableDone(UInt16 enabled_path); |
| |
| /*============================================================================= |
| // Functions |
| //============================================================================= |
| */ |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_Init |
| // |
| // Description: Inititialize audio system |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_Init(void) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_Init\n"); |
| |
| if (sAudDrv.isRunning == TRUE) |
| return; |
| |
| /* register DSP VPU status processing handlers */ |
| |
| AUDIO_MODEM(CSL_RegisterVPUCaptureStatusHandler |
| ((VPUCaptureStatusCB_t) &VPU_Capture_Request);) |
| #if 0 /*These features are not needed in LMP now. */ |
| AUDIO_MODEM(CSL_RegisterVPURenderStatusHandler |
| ((VPURenderStatusCB_t) &VPU_Render_Request);) |
| AUDIO_MODEM(CSL_RegisterUSBStatusHandler |
| ((USBStatusCB_t) &AUDDRV_USB_HandleDSPInt);) |
| #endif |
| AUDIO_MODEM(CSL_RegisterVoIPStatusHandler |
| ((VoIPStatusCB_t) &VOIP_ProcessVOIPDLDone);) |
| AUDIO_MODEM(CSL_RegisterMainAMRStatusHandler |
| ((MainAMRStatusCB_t) &AP_ProcessStatusMainAMRDone);) |
| AUDIO_MODEM(CSL_RegisterARM2SPRenderStatusHandler |
| ((ARM2SPRenderStatusCB_t) &ARM2SP_Render_Request);) |
| AUDIO_MODEM(CSL_RegisterARM2SP2RenderStatusHandler |
| ((ARM2SP2RenderStatusCB_t) &ARM2SP2_Render_Request);) |
| AUDIO_MODEM(CSL_RegisterAudioLogHandler |
| ((AudioLogStatusCB_t) &AUDLOG_ProcessLogChannel);) |
| AUDIO_MODEM(CSL_RegisterVOIFStatusHandler |
| ((VOIFStatusCB_t) &VOIF_Buffer_Request);) |
| CSL_RegisterAudioEnableDoneHandler |
| ((AudioEnableDoneStatusCB_t) |
| &AP_ProcessAudioEnableDone); |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| CSL_RegisterExtModemCallDoneHandler |
| ((AudioEnableDoneStatusCB_t) |
| &AP_ProcessExtModemCallDone); |
| |
| init_completion(&extModemCallDone); |
| #endif |
| |
| Audio_InitRpc(); |
| sAudDrv.isRunning = TRUE; |
| init_completion(&audioEnableDone); |
| } |
| |
| /********************************************************************** |
| // |
| // Shutdown audio driver task |
| // |
| // @return void |
| // @note |
| **********************************************************************/ |
| void AUDDRV_Shutdown(void) |
| { |
| if (sAudDrv.isRunning == FALSE) |
| return; |
| |
| sAudDrv.isRunning = FALSE; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_Telephony_Init |
| // |
| // Description: Initialize audio system for voice call |
| // |
| //============================================================================= |
| */ |
| /*Prepare DSP before turn on hardware audio path for voice call. |
| // This is part of the control sequence for starting telephony audio.*/ |
| void AUDDRV_Telephony_Init(AUDIO_SOURCE_Enum_t mic, AUDIO_SINK_Enum_t speaker, |
| AudioMode_t mode, AudioApp_t app, int bNeedDualMic, |
| int bmuteVoiceCall) |
| { |
| #if defined(ENABLE_DMA_VOICE) |
| UInt16 dma_mic_spk; |
| #endif |
| Boolean ec_enable_from_sysparm = dspECEnable; |
| Boolean ns_enable_from_sysparm = dspNSEnable; |
| |
| audio_rpc_clear_flag_vc_rel_by_modem(); |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| AUDDRV_ExtModem_Telephony_Init(mic, speaker, |
| mode, app, bNeedDualMic, |
| bmuteVoiceCall); |
| #endif |
| |
| /*-///////////////////////////////////////////////////////////////// |
| // Phone Setup Sequence |
| // 1. Init CAPH HW |
| // 2. Send DSP command AUDDRV_DSPCMD_AUDIO_ENABLE |
| // 3. If requires 48KHz for example in IHF mode, |
| Send VPRIPCMDQ_ENABLE_48KHZ_SPEAKER_OUTPUT |
| ////////////////////////////////////////////////////////////////-*/ |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "AUDDRV_Telephony_Init app %d, mode %d, bNeedDualMic %d\n", |
| app, mode, bNeedDualMic); |
| csl_caph_ControlHWClock(TRUE); /*enable clock before any DSP command*/ |
| |
| currVoiceMic = mic; |
| currVoiceSpkr = speaker; |
| |
| audio_control_dsp(AUDDRV_DSPCMD_MUTE_DSP_UL, 0, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_EC_NS_ON, FALSE, FALSE, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_DUAL_MIC_ON, FALSE, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_TURN_UL_COMPANDEROnOff, FALSE, |
| 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_UL, FALSE, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_DL, FALSE, 0, 0, 0, 0); |
| |
| if (app == AUDIO_APP_VOICE_CALL_WB) { |
| AUDDRV_Telephony_InitHW(mic, speaker, AUDIO_SAMPLING_RATE_16000, |
| bNeedDualMic); |
| #if defined(ENABLE_DMA_VOICE) |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_16000); |
| #endif |
| } else { |
| AUDDRV_Telephony_InitHW(mic, speaker, AUDIO_SAMPLING_RATE_8000, |
| bNeedDualMic); |
| #if defined(ENABLE_DMA_VOICE) |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_8000); |
| #endif |
| } |
| |
| /* Set new filter coef, sidetone filters, gains. */ |
| AUDDRV_SetAudioMode(mode, app, |
| telephonyPathID.ulPathID, |
| telephonyPathID.ul2PathID, |
| telephonyPathID.dlPathID); |
| |
| #if defined(ENABLE_DMA_VOICE) |
| if (speaker == AUDIO_SINK_LOUDSPK) { |
| csl_dsp_caph_control_aadmac_disable_path((UInt16) |
| (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN)); |
| /* dma_mic_spk = (UInt16) DSP_AADMAC_PRI_MIC_EN;*/ |
| dma_mic_spk = ((UInt16)(DSP_AADMAC_PRI_MIC_EN)) | ((UInt16) |
| (DSP_AADMAC_IHF_SPKR_EN)) | |
| ((UInt16)DSP_AADMAC_RETIRE_DS_CMD); |
| |
| csl_dsp_caph_control_aadmac_enable_path(dma_mic_spk); |
| } else { |
| csl_dsp_caph_control_aadmac_disable_path((UInt16) |
| (DSP_AADMAC_IHF_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN)); |
| dma_mic_spk = |
| (UInt16) (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD); |
| if (bNeedDualMic) |
| dma_mic_spk |= (UInt16) (DSP_AADMAC_SEC_MIC_EN); |
| |
| if (speaker == AUDIO_SINK_BTM) |
| dma_mic_spk |= (UInt16) |
| (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN); |
| |
| csl_dsp_caph_control_aadmac_enable_path(dma_mic_spk); |
| } |
| #endif |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, TRUE, 0, 0, 0, 0); |
| |
| if (curCallMode != PTT_CALL) |
| audio_control_dsp( |
| AUDDRV_DSPCMD_AUDIO_CONNECT_DL, TRUE, 0, 0, 0, 0); |
| else |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_Telephony_Init: " |
| "PTT, skip AUDIO_CONNECT_DL\n"); |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_UL, TRUE, 0, 0, 0, 0); |
| |
| /* audio_control_dsp(AUDDRV_DSPCMD_EC_NS_ON, TRUE, TRUE, 0, 0, 0); */ |
| audio_control_dsp(AUDDRV_DSPCMD_EC_NS_ON, ec_enable_from_sysparm, |
| ns_enable_from_sysparm, 0, 0, 0); |
| |
| if (bNeedDualMic == TRUE) |
| audio_control_dsp(AUDDRV_DSPCMD_DUAL_MIC_ON, TRUE, 0, 0, 0, 0); |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_TURN_UL_COMPANDEROnOff, |
| TRUE, 0, 0, 0, 0); |
| |
| if (bmuteVoiceCall == FALSE) |
| audio_control_dsp(AUDDRV_DSPCMD_UNMUTE_DSP_UL, 0, 0, 0, 0, 0); |
| |
| /* per call basis: enable the DTX by calling stack api when call connected */ |
| audio_control_generic(AUDDRV_CPCMD_ENABLE_DSP_DTX, TRUE, 0, 0, 0, 0); |
| |
| return; |
| } |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| static void AUDDRV_ExtModem_Telephony_Init(AUDIO_SOURCE_Enum_t mic, |
| AUDIO_SINK_Enum_t speaker, |
| AudioMode_t mode, AudioApp_t app, int bNeedDualMic, |
| int bmuteVoiceCall) |
| { |
| CSL_CAPH_HWCTRL_CONFIG_t config; |
| unsigned long jiff_in = 0; |
| |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_ExtModem_Telephony_Init\n"); |
| csl_caph_ControlHWClock(TRUE); /*enable clock before any DSP command*/ |
| |
| /* DL */ |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = 0; |
| config.source = CSL_CAPH_DEV_SSP_RX; |
| config.sink = CSL_CAPH_DEV_DSP_throughMEM; |
| config.dmaCH = CSL_CAPH_DMA_CH15; |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_8000; |
| config.snk_sampleRate = AUDIO_SAMPLING_RATE_8000; |
| config.chnlNum = AUDIO_CHANNEL_MONO; |
| config.bitPerSample = 16; |
| |
| dlExtModemPathID = csl_caph_hwctrl_extModem_SetupPath(config); |
| |
| /* UL */ |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = 0; |
| config.source = CSL_CAPH_DEV_DSP_throughMEM; |
| config.sink = CSL_CAPH_DEV_SSP_TX; |
| config.dmaCH = CSL_CAPH_DMA_CH16; |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_8000; |
| config.snk_sampleRate = AUDIO_SAMPLING_RATE_8000; |
| config.chnlNum = AUDIO_CHANNEL_MONO; |
| config.bitPerSample = 16; |
| |
| ulExtModemPathID = csl_caph_hwctrl_extModem_SetupPath(config); |
| |
| csl_caph_hwctrl_extModem_StartPath(ulExtModemPathID, dlExtModemPathID); |
| |
| csl_dsp_ext_modem_call(TRUE); |
| |
| jiff_in = wait_for_completion_interruptible_timeout( |
| &extModemCallDone, |
| timeout_jiff); |
| if (!jiff_in) { |
| aError("!!!Timeout on COMMAND_EXT_MODEM_CALL" |
| " resp!!!\n"); |
| init_completion(&extModemCallDone); |
| } |
| } |
| #endif |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_Telephony_RateChange |
| // |
| // Description: Change the sample rate for voice call |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_Telephony_RateChange(AudioMode_t mode, |
| AudioApp_t audio_app, int bNeedDualMic, int bmuteVoiceCall) |
| { |
| inCallRateChange = TRUE; |
| AUDDRV_Telephony_Deinit(); |
| AUDDRV_Telephony_Init(currVoiceMic, currVoiceSpkr, mode, audio_app, |
| bNeedDualMic, bmuteVoiceCall); |
| inCallRateChange = FALSE; |
| return; |
| } |
| |
| /********************************************************************* |
| // |
| // Registers callback for rate change request |
| // |
| // @param callback function |
| // @return void |
| // @note |
| **********************************************************************/ |
| |
| void AUDDRV_RegisterRateChangeCallback(audio_codecId_handler_t codecId_cb) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_RegisterRateChangeCallback, 0x%lx\n", |
| (long unsigned int)codecId_cb); |
| codecId_handler = codecId_cb; |
| } |
| |
| /********************************************************************* |
| // |
| // Registers callback for handling cp reset |
| // |
| // @param callback function |
| // @return void |
| // @note |
| **********************************************************************/ |
| |
| void AUDDRV_RegisterHandleCPResetCB( |
| audio_handleCPReset_handler_t cpReset_cb) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_RegisterHandleCPResetCB"); |
| cpReset_handler = cpReset_cb; |
| } |
| |
| /********************************************************************* |
| // |
| // Function Name: AUDDRV_EC |
| // |
| // Description: DSP Echo cancellation ON/OFF |
| // |
| **********************************************************************/ |
| void AUDDRV_EC(Boolean enable, UInt32 arg) |
| { |
| dspECEnable = enable; |
| } |
| |
| /********************************************************************* |
| // |
| // Function Name: AUDDRV_NS |
| // |
| // Description: DSP Noise Suppression ON/OFF |
| // |
| **********************************************************************/ |
| void AUDDRV_NS(Boolean enable) |
| { |
| dspNSEnable = enable; |
| } |
| |
| /********************************************************************* |
| // |
| // Post rate change message for telephony session |
| // |
| // @param codec ID |
| // @return void |
| // @note |
| **********************************************************************/ |
| void AUDDRV_Telephone_RequestRateChange(int codecID) |
| { |
| if (codecId_handler != NULL) |
| codecId_handler(codecID); |
| } |
| |
| /********************************************************************* |
| // |
| // Post cp reset message |
| // |
| // @param none |
| // @return void |
| // @note |
| **********************************************************************/ |
| void AUDDRV_HandleCPReset(Boolean cp_reset_start) |
| { |
| if (cpReset_handler != NULL) |
| cpReset_handler(cp_reset_start); |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_Telephony_Deinit |
| // |
| // Description: DeInitialize audio system for voice call |
| // |
| //============================================================================= |
| */ |
| |
| /*Prepare DSP before turn off hardware audio path for voice call. |
| // This is part of the control sequence for ending telephony audio.*/ |
| void AUDDRV_Telephony_Deinit(void) |
| { |
| #if defined(ENABLE_DMA_VOICE) |
| UInt16 dma_mic_spk; |
| #endif |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s voiceOut %d voiceRecOn %d\n", |
| __func__, voicePlayOutpathEnabled, voiceRecOn); |
| |
| /* continues speech playback when end the phone call. |
| // continues speech recording when end the phone call.*/ |
| /* if ( FALSE==vopath_enabled && FALSE==DspVoiceIfActive_DL() |
| && FALSE==vipath_enabled ) |
| { */ |
| |
| /* a quick fix not to disable voice path for speech playbck |
| when end the phone call. */ |
| /* disable the DTX by calling stack api when call disconnected */ |
| if (voicePlayOutpathEnabled == FALSE) { |
| audio_control_generic(AUDDRV_CPCMD_ENABLE_DSP_DTX, FALSE, 0, 0, |
| 0, 0); |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_DL, FALSE, |
| 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_UL, FALSE, |
| 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_EC_NS_ON, FALSE, FALSE, |
| 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_DUAL_MIC_ON, FALSE, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_TURN_UL_COMPANDEROnOff, |
| FALSE, 0, 0, 0, 0); |
| |
| #if defined(ENABLE_DMA_VOICE) |
| dma_mic_spk = |
| (UInt16) (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) (DSP_AADMAC_IHF_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_SEC_MIC_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN); |
| csl_dsp_caph_control_aadmac_disable_path(dma_mic_spk); |
| #endif |
| audio_control_dsp(AUDDRV_DSPCMD_MUTE_DSP_UL, 0, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, FALSE, |
| 0, 0, 0, 0); |
| AUDDRV_Telephony_DeinitHW(); |
| } |
| |
| if (!inCallRateChange) { |
| currVoiceMic = AUDIO_SOURCE_UNDEFINED; |
| currVoiceSpkr = AUDIO_SINK_UNDEFINED; |
| } |
| |
| if (voiceRecOn) |
| AUDDRV_EnableDSPInput(voiceInMic, voiceInSr); |
| |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| AUDDRV_ExtModem_Telephony_Deinit(); |
| #endif |
| |
| audio_rpc_clear_flag_vc_rel_by_modem(); |
| |
| return; |
| } |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_ExtModem_Telephony_Deinit |
| // |
| // Description: DeInitialize audio system for voice call |
| // |
| //============================================================================= |
| */ |
| static void AUDDRV_ExtModem_Telephony_Deinit(void) |
| { |
| unsigned long jiff_in = 0; |
| |
| csl_dsp_ext_modem_call(FALSE); |
| |
| jiff_in = wait_for_completion_interruptible_timeout( |
| &extModemCallDone, |
| timeout_jiff); |
| if (!jiff_in) { |
| aError("!!!Timeout on COMMAND_EXT_MODEM_CALL" |
| " resp!!!\n"); |
| init_completion(&extModemCallDone); |
| } |
| |
| /*keep clock on until DSP response is back.*/ |
| csl_caph_hwctrl_extModem_StopPath(ulExtModemPathID, dlExtModemPathID); |
| } |
| #endif |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_EnableDSPOutput |
| // |
| // Description: Enable audio DSP output for voice call |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_EnableDSPOutput(AUDIO_SINK_Enum_t sink, |
| AUDIO_SAMPLING_RATE_t sample_rate) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "%s mixer %d, sample_rate %u\n", |
| __func__, sink, sample_rate); |
| |
| currVoiceSpkr = sink; |
| |
| #if defined(ENABLE_DMA_VOICE) |
| if (sample_rate == AUDIO_SAMPLING_RATE_8000) { |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_8000); |
| if (sink == AUDIO_SINK_BTM) |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| else |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| } else { |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_16000); |
| if (sink == AUDIO_SINK_BTM) |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| else |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_SPKR_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| } |
| #endif |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, 1, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_DL, 1, 0, 0, 0, 0); |
| |
| voicePlayOutpathEnabled = TRUE; |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s voicePlayOutpathEnabled=%d", |
| __func__, voicePlayOutpathEnabled); |
| } |
| |
| /* ============================================================================ |
| // |
| // Function Name: AUDDRV_DisableDSPOutput |
| // |
| // Description: Disable audio DSP output for playback |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_DisableDSPOutput(void) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "%s", __func__); |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_DL, FALSE, 0, 0, 0, |
| 0); |
| |
| #if defined(ENABLE_DMA_VOICE) |
| csl_dsp_caph_control_aadmac_disable_path(((UInt16) |
| DSP_AADMAC_SPKR_EN) | ((UInt16)(DSP_AADMAC_IHF_SPKR_EN)) | |
| ((UInt16)(DSP_AADMAC_PACKED_16BIT_IN_OUT_EN))); |
| #endif |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, FALSE, 0, 0, 0, 0); |
| |
| voicePlayOutpathEnabled = FALSE; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_EnableDSPInput |
| // |
| // Description: Enable audio DSP input for voice record |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_EnableDSPInput(AUDIO_SOURCE_Enum_t source, |
| AUDIO_SAMPLING_RATE_t sample_rate) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "%s source %d voiceRecOn %d, ulPath %d\n", |
| __func__, source, voiceRecOn, telephonyPathID.ulPathID); |
| |
| voiceRecOn = TRUE; |
| voiceInMic = source; |
| voiceInSr = sample_rate; |
| /*only in non-call mode, tell DSP to start UL*/ |
| if (telephonyPathID.ulPathID) |
| return; |
| |
| #if defined(ENABLE_DMA_VOICE) |
| if (sample_rate == AUDIO_SAMPLING_RATE_8000) { |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_8000); |
| if (source == AUDIO_SOURCE_BTM) |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) |
| (DSP_AADMAC_RETIRE_DS_CMD) | |
| (UInt16) |
| (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN)); |
| else { |
| if (currVoiceSpkr != AUDIO_SINK_BTM) /* check spkr */ |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| } |
| } else { |
| csl_dsp_caph_control_aadmac_set_samp_rate |
| (AUDIO_SAMPLING_RATE_16000); |
| if (source == AUDIO_SOURCE_BTM) |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) |
| (DSP_AADMAC_RETIRE_DS_CMD) | |
| (UInt16) |
| (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN)); |
| else { |
| if (currVoiceSpkr != AUDIO_SINK_BTM) /* check spkr */ |
| csl_dsp_caph_control_aadmac_enable_path((UInt16) |
| (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) (DSP_AADMAC_RETIRE_DS_CMD)); |
| } |
| } |
| #endif |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, 1, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_UL, 1, 0, 0, 0, 0); |
| /* AUDDRV_DSPCMD_AUDIO_CONNECT should be called after |
| AUDDRV_DSPCMD_AUDIO_ENABLE */ |
| |
| /* |
| When voice call ends, AUDDRV_DSPCMD_MUTE_DSP_UL is being sent to DSP and |
| this command mutes UL record gain |
| Not sure why this is done and there is no clarification if we really |
| need to send the MUTE UL command when disconnecting the voice call. |
| For now, when voice record is started, UMUTE UL command will be sent */ |
| |
| audio_control_dsp(AUDDRV_DSPCMD_UNMUTE_DSP_UL, 0, 0, 0, 0, 0); |
| |
| currVoiceMic = source; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_DisableDSPInput |
| // |
| // Description: Disable audio DSP input for record |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_DisableDSPInput(int stop) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "%s stop %d, voiceRecOn %d, ulPath %d\n", |
| __func__, stop, voiceRecOn, telephonyPathID.ulPathID); |
| |
| if (stop) |
| voiceRecOn = FALSE; |
| /*only in non-call mode, tell DSP to stop UL*/ |
| if (telephonyPathID.ulPathID) |
| return; |
| |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_CONNECT_UL, FALSE, 0, 0, 0, 0); |
| #if defined(ENABLE_DMA_VOICE) |
| csl_dsp_caph_control_aadmac_disable_path((UInt16) |
| (DSP_AADMAC_PRI_MIC_EN) | |
| (UInt16) (DSP_AADMAC_PACKED_16BIT_IN_OUT_EN)); |
| #endif |
| audio_control_dsp(AUDDRV_DSPCMD_MUTE_DSP_UL, 0, 0, 0, 0, 0); |
| audio_control_dsp(AUDDRV_DSPCMD_AUDIO_ENABLE, FALSE, 0, 0, 0, 0); |
| |
| currVoiceMic = AUDIO_SOURCE_UNDEFINED; |
| } |
| |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetAudioMode_voicerecord |
| // |
| // Description: set audio mode for voice call. |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_SetAudioMode_voicerecord(AudioMode_t audio_mode, |
| AudioApp_t audio_app, |
| CSL_CAPH_PathID ulPathID, |
| CSL_CAPH_PathID ul2PathID) |
| { |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s mode==%d, app=%d\n\r", __func__, |
| audio_mode, audio_app); |
| |
| RPC_SetProperty(RPC_PROP_AUDIO_MODE, |
| (UInt32) (audio_mode + |
| audio_app * AUDIO_MODE_NUMBER)); |
| |
| audio_control_generic(AUDDRV_CPCMD_PassAudioMode, |
| (UInt32) audio_mode, (UInt32) audio_app, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetAudioMode, |
| (UInt32) (audio_mode + |
| audio_app * AUDIO_MODE_NUMBER), |
| (UInt32) audio_app, 0, 0, 0); |
| |
| /*load speaker EQ filter and Mic EQ filter from sysparm to DSP*/ |
| /* It means mic1, mic2, speaker */ |
| if (userEQOn == FALSE) { |
| /* Use the old code, before CP function |
| audio_control_BuildDSPUlCompfilterCoef() is updated to |
| handle the mode properly.*/ |
| if (audio_app == AUDIO_APP_VOICE_CALL_WB) |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + AUDIO_MODE_NUMBER, 7, 0, 0, 0); |
| else |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode % AUDIO_MODE_NUMBER, 7, 0, 0, 0); |
| /* |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app*AUDIO_MODE_NUMBER, |
| 7, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 1, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 2, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 4, 0, 0, 0); |
| */ |
| } |
| |
| AUDDRV_SetAudioMode_Mic(audio_mode, audio_app, ulPathID, ul2PathID); |
| } |
| |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetAudioMode |
| // |
| // Description: set audio mode for voice call. |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_SetAudioMode(AudioMode_t audio_mode, AudioApp_t audio_app, |
| CSL_CAPH_PathID ulPathID, |
| CSL_CAPH_PathID ul2PathID, |
| CSL_CAPH_PathID dlPathID) |
| { |
| SetAudioMode_Sp_t sp_struct; |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s mode==%d, app=%d\n\r", __func__, |
| audio_mode, audio_app); |
| |
| RPC_SetProperty(RPC_PROP_AUDIO_MODE, |
| (UInt32) (audio_mode + |
| audio_app * AUDIO_MODE_NUMBER)); |
| |
| audio_control_generic(AUDDRV_CPCMD_PassAudioMode, |
| (UInt32) audio_mode, (UInt32) audio_app, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetAudioMode, |
| (UInt32) (audio_mode + |
| audio_app * AUDIO_MODE_NUMBER), |
| (UInt32) audio_app, 0, 0, 0); |
| |
| /*load speaker EQ filter and Mic EQ filter from sysparm to DSP*/ |
| /* It means mic1, mic2, speaker */ |
| if (userEQOn == FALSE) { |
| /* Use the old code, before CP function |
| audio_control_BuildDSPUlCompfilterCoef() is updated to |
| handle the mode properly.*/ |
| if (audio_app == AUDIO_APP_VOICE_CALL_WB) |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + AUDIO_MODE_NUMBER, 7, 0, 0, 0); |
| else |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode % AUDIO_MODE_NUMBER, 7, 0, 0, 0); |
| /* |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app*AUDIO_MODE_NUMBER, |
| 7, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 1, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 2, 0, 0, 0); |
| audio_control_generic(AUDDRV_CPCMD_SetFilter, |
| audio_mode + audio_app * AUDIO_MODE_NUMBER, |
| 4, 0, 0, 0); |
| */ |
| } |
| /* else */ |
| /*There is no need for this function to load the ECI-headset-provided |
| speaker EQ filter and Mic EQ filter to DSP. |
| //The ECI headset enable/disable request comes with the data. |
| It means we'll get the coefficients every time if ECI headset on. */ |
| /* audio_cmf_filter((AudioCompfilter_t *) ©_of_AudioCompfilter ); */ |
| |
| AUDDRV_SetAudioMode_Mic(audio_mode, audio_app, ulPathID, ul2PathID); |
| |
| sp_struct.mode = audio_mode; |
| sp_struct.app = audio_app; |
| sp_struct.pathID = dlPathID; |
| sp_struct.inHWlpbk = FALSE; |
| sp_struct.mixInGain_mB = GAIN_SYSPARM; |
| sp_struct.mixInGainR_mB = GAIN_SYSPARM; |
| sp_struct.mixOutGain_mB = GAIN_SYSPARM; |
| sp_struct.mixOutGainR_mB = GAIN_SYSPARM; |
| AUDDRV_SetAudioMode_Speaker(sp_struct); |
| } |
| |
| #ifdef CONFIG_ENABLE_SSMULTICAST |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetAudioMode_Multicast |
| // |
| // Description: set audio mode for IHF+HS Multicast. |
| // For SS multicase both HS and IHF params are from mode SPEAKER |
| //============================================================================= |
| */ |
| void AUDDRV_SetAudioMode_Multicast(SetAudioMode_Sp_t param) |
| { |
| int mixInGain, mixOutGain, mixBitSel; /* Register value. */ |
| int mixInGainR, mixOutGainR, mixBitSelR; /* Register value. */ |
| CSL_CAPH_HWConfig_Table_t *path = NULL; |
| CSL_CAPH_MIXER_e outChnl = CSL_CAPH_SRCM_CH_NONE; |
| |
| #ifdef CONFIG_BCM_MODEM |
| SysAudioParm_t *p; |
| #else |
| AudioSysParm_t *p; |
| #endif |
| /*For SS Multicast mode is always AUDIO_MODE_SPEAKERPHONE*/ |
| p = &(AudParmP()[AUDIO_MODE_SPEAKERPHONE + \ |
| param.app * AUDIO_MODE_NUMBER]); |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s mode=%d, app %d, pathID %d\n", |
| __func__, param.mode, param.app, param.pathID); |
| |
| mixInGain = mixOutGain = mixBitSel = 0; |
| mixInGainR = mixOutGainR = mixBitSelR = 0; |
| /* Load the speaker gains form sysparm. */ |
| |
| /*determine which mixer output to apply the gains to */ |
| |
| switch (param.mode) { |
| case AUDIO_MODE_HEADSET: |
| case AUDIO_MODE_TTY: |
| outChnl = CSL_CAPH_SRCM_STEREO_CH1; |
| break; |
| |
| case AUDIO_MODE_SPEAKERPHONE: |
| outChnl = csl_caph_FindMixer(CSL_CAPH_DEV_IHF, 0); |
| break; |
| default: |
| break; |
| } |
| |
| /*Load HW Mixer gains from sysparm */ |
| |
| if (param.mixInGain_mB == GAIN_SYSPARM && |
| param.mixInGainR_mB == GAIN_SYSPARM) { |
| /*GAIN_SYSPARM means use sysparm*/ |
| mixInGain = (short)p->srcmixer_input_gain_l; /* Q13p2 dB */ |
| mixInGain = mixInGain * 25; /* into mB */ |
| mixInGainR = (short)p->srcmixer_input_gain_r; /* Q13p2 dB */ |
| mixInGainR = mixInGainR * 25; /* into mB */ |
| } else if (param.mixInGain_mB == GAIN_SYSPARM) { |
| mixInGain = (short)p->srcmixer_input_gain_l; /* Q13p2 dB */ |
| mixInGain = mixInGain * 25; /* into mB */ |
| mixInGainR = param.mixInGainR_mB; |
| } else if (param.mixInGainR_mB == GAIN_SYSPARM) { |
| mixInGainR = (short)p->srcmixer_input_gain_r; /* Q13p2 dB */ |
| mixInGainR = mixInGainR * 25; /* into mB */ |
| mixInGain = param.mixInGain_mB; |
| } else { |
| mixInGain = param.mixInGain_mB; |
| mixInGainR = param.mixInGainR_mB; |
| } |
| |
| /*determine which mixer input to apply the gains to */ |
| |
| if (param.pathID >= 1) |
| path = csl_caph_FindPath(param.pathID); |
| |
| if (path != 0) { |
| int i, j; |
| for (i = 0; i < MAX_SINK_NUM; i++) |
| for (j = 0; j < MAX_BLOCK_NUM; j++) |
| if (path->srcmRoute[i][j].outChnl != |
| CSL_CAPH_SRCM_CH_NONE) { |
| /*and supposedly |
| path->srcmRoute[i][j].sink |
| matches this speaker*/ |
| |
| outChnl = path->srcmRoute[i][j].outChnl; |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s pathID %d outChnl 0x%x inChnl 0x%x\n", |
| __func__, param.pathID, outChnl, |
| path->srcmRoute[i][j].inChnl); |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "mixInGain 0x%x, mixInGainR 0x%x\n", |
| mixInGain, mixInGainR); |
| csl_srcmixer_setMixInGain( |
| path->srcmRoute[i][j].inChnl, |
| path->srcmRoute[i][j].outChnl, |
| mixInGain, mixInGainR); |
| } |
| } else { |
| aError( |
| "AUDDRV_SetAudioMode_Multicast can not find path\n"); |
| } |
| |
| if (outChnl) { |
| if (param.mixOutGain_mB == GAIN_SYSPARM && |
| param.mixOutGainR_mB == GAIN_SYSPARM) { |
| /* Q13p2 dB */ |
| mixOutGain = (short)p->srcmixer_output_fine_gain_l; |
| mixOutGain = mixOutGain * 25; /*into mB */ |
| mixOutGainR = (short)p->srcmixer_output_fine_gain_r; |
| mixOutGainR = mixOutGainR * 25; /*into mB */ |
| } else if (param.mixOutGain_mB == GAIN_SYSPARM) { |
| mixOutGain = (short)p->srcmixer_output_fine_gain_l; |
| mixOutGain = mixOutGain * 25; /*into mB */ |
| mixOutGainR = param.mixOutGainR_mB; |
| } else if (param.mixOutGainR_mB == GAIN_SYSPARM) { |
| mixOutGainR = (short)p->srcmixer_output_fine_gain_r; |
| mixOutGainR = mixOutGainR * 25; /*into mB */ |
| mixOutGain = param.mixOutGain_mB; |
| } else { |
| mixOutGain = param.mixOutGain_mB; |
| mixOutGainR = param.mixOutGainR_mB; |
| } |
| |
| /* Q13p2 dB */ |
| mixBitSel = (short)p->srcmixer_output_coarse_gain_l; |
| mixBitSel = mixBitSel / 24; |
| /* bit_shift */ |
| |
| mixBitSelR = (short)p->srcmixer_output_coarse_gain_r; |
| mixBitSelR = mixBitSelR / 24; |
| /* bit_shift */ |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s : mixOutGain 0x%x, mixOutGainR 0x%x, " |
| "mixBitSel %d, mixBitSelR %d\n", |
| __func__, mixOutGain, mixOutGainR, |
| mixBitSel, mixBitSelR); |
| csl_srcmixer_setMixBitSel(outChnl, mixBitSel, mixBitSelR); |
| csl_srcmixer_setMixOutGain(outChnl, mixOutGain, mixOutGainR); |
| } |
| |
| |
| /* Do not enable/disable sidetone path based on sysparm when in HW loopback */ |
| if (!param.inHWlpbk) { |
| /*Config sidetone */ |
| void *coef = NULL; |
| UInt16 gain = 0; |
| UInt16 enable = 0; |
| |
| enable = p->hw_sidetone_enable; |
| if (!enable) { |
| AUDDRV_HW_DisableSideTone(param.mode); |
| } else { |
| /*first step: enable sidetone */ |
| AUDDRV_HW_EnableSideTone(param.mode); |
| |
| /*second step: set filter and gain. */ |
| coef = (void *)&(p->hw_sidetone_eq[0]); |
| AUDDRV_HW_SetFilter(AUDDRV_SIDETONE_FILTER, coef); |
| |
| gain = p->hw_sidetone_gain; |
| csl_caph_audioh_sidetone_set_gain(gain); |
| } |
| } |
| } |
| #endif |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetAudioMode_Speaker |
| // |
| // Description: set audio mode. |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_SetAudioMode_Speaker(SetAudioMode_Sp_t param) |
| { |
| int mixInGain, mixOutGain, mixBitSel; /* Register value. */ |
| int mixInGainR, mixOutGainR, mixBitSelR; /* Register value. */ |
| CSL_CAPH_HWConfig_Table_t *path = NULL; |
| CSL_CAPH_MIXER_e outChnl = CSL_CAPH_SRCM_CH_NONE; |
| |
| #ifdef CONFIG_BCM_MODEM |
| SysAudioParm_t *p; |
| #else |
| AudioSysParm_t *p; |
| #endif |
| |
| p = &(AudParmP()[param.mode + param.app * AUDIO_MODE_NUMBER]); |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s mode=%d, app %d, pathID %d\n", |
| __func__, param.mode, param.app, param.pathID); |
| |
| mixInGain = mixOutGain = mixBitSel = 0; |
| mixInGainR = mixOutGainR = mixBitSelR = 0; |
| /* Load the speaker gains form sysparm. */ |
| |
| /*determine which mixer output to apply the gains to */ |
| |
| switch (param.mode) { |
| case AUDIO_MODE_HANDSET: |
| case AUDIO_MODE_HAC: |
| outChnl = CSL_CAPH_SRCM_STEREO_CH2_L; |
| break; |
| |
| case AUDIO_MODE_HEADSET: |
| case AUDIO_MODE_TTY: |
| /*outChnl = (CSL_CAPH_SRCM_STEREO_CH1_L | CSL_CAPH_SRCM_STEREO_CH1_R);*/ |
| outChnl = CSL_CAPH_SRCM_STEREO_CH1; |
| break; |
| |
| case AUDIO_MODE_SPEAKERPHONE: |
| outChnl = csl_caph_FindMixer(CSL_CAPH_DEV_IHF, 0); |
| break; |
| |
| case AUDIO_MODE_BLUETOOTH: |
| #ifdef CONFIG_AUDIO_FEATURE_SET_DISABLE_ECNS |
| case AUDIO_MODE_HANDSFREE: |
| #endif |
| outChnl = |
| csl_caph_hwctrl_GetMixerOutChannel(CSL_CAPH_DEV_BT_SPKR); |
| break; |
| |
| default: |
| break; |
| } |
| |
| /*Load HW Mixer gains from sysparm */ |
| |
| if (param.mixInGain_mB == GAIN_SYSPARM && |
| param.mixInGainR_mB == GAIN_SYSPARM) { |
| /*GAIN_SYSPARM means use sysparm*/ |
| mixInGain = (short)p->srcmixer_input_gain_l; /* Q13p2 dB */ |
| mixInGain = mixInGain * 25; /* into mB */ |
| mixInGainR = (short)p->srcmixer_input_gain_r; /* Q13p2 dB */ |
| mixInGainR = mixInGainR * 25; /* into mB */ |
| } else if (param.mixInGain_mB == GAIN_SYSPARM) { |
| mixInGain = (short)p->srcmixer_input_gain_l; /* Q13p2 dB */ |
| mixInGain = mixInGain * 25; /* into mB */ |
| mixInGainR = param.mixInGainR_mB; |
| } else if (param.mixInGainR_mB == GAIN_SYSPARM) { |
| mixInGainR = (short)p->srcmixer_input_gain_r; /* Q13p2 dB */ |
| mixInGainR = mixInGainR * 25; /* into mB */ |
| mixInGain = param.mixInGain_mB; |
| } else { |
| mixInGain = param.mixInGain_mB; |
| mixInGainR = param.mixInGainR_mB; |
| } |
| if (param.mixOutGain_mB == GAIN_SYSPARM && |
| param.mixOutGainR_mB == GAIN_SYSPARM) { |
| /* Q13p2 dB */ |
| mixOutGain = (short)p->srcmixer_output_fine_gain_l; |
| mixOutGain = mixOutGain * 25; /*into mB */ |
| mixOutGainR = (short)p->srcmixer_output_fine_gain_r; |
| mixOutGainR = mixOutGainR * 25; /*into mB */ |
| } else if (param.mixOutGain_mB == GAIN_SYSPARM) { |
| mixOutGain = (short)p->srcmixer_output_fine_gain_l; |
| mixOutGain = mixOutGain * 25; /*into mB */ |
| mixOutGainR = param.mixOutGainR_mB; |
| } else if (param.mixOutGainR_mB == GAIN_SYSPARM) { |
| mixOutGainR = (short)p->srcmixer_output_fine_gain_r; |
| mixOutGainR = mixOutGainR * 25; /*into mB */ |
| mixOutGain = param.mixOutGain_mB; |
| } else { |
| mixOutGain = param.mixOutGain_mB; |
| mixOutGainR = param.mixOutGainR_mB; |
| |
| /*aTrace(LOG_AUDIO_DRIVER, |
| "%s copy mixOutGain %d, %d\n", |
| __func__, mixOutGain, mixOutGainR);*/ |
| } |
| |
| /* Q13p2 dB */ |
| mixBitSel = (short)p->srcmixer_output_coarse_gain_l; |
| mixBitSel = mixBitSel / 24; |
| /* bit_shift */ |
| |
| mixBitSelR = (short)p->srcmixer_output_coarse_gain_r; |
| mixBitSelR = mixBitSelR / 24; |
| /* bit_shift */ |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s: mixOutGain 0x%x, mixOutGainR 0x%x, " |
| "mixBitSel %d, mixBitSelR %d\n", |
| __func__, mixOutGain, mixOutGainR, |
| mixBitSel, mixBitSelR); |
| |
| /*determine which which mixer input to apply the gains to */ |
| |
| if (param.pathID >= 1) |
| path = csl_caph_FindPath(param.pathID); |
| |
| if (path != 0) { |
| /*if (path->sink[0] == CSL_CAPH_DEV_DSP_throughMEM) |
| outChnl = path->srcmRoute[0][0].outChnl;*/ |
| |
| int i, j; |
| for (i = 0; i < MAX_SINK_NUM; i++) |
| for (j = 0; j < MAX_BLOCK_NUM; j++) |
| if (path->srcmRoute[i][j].outChnl != |
| CSL_CAPH_SRCM_CH_NONE) { |
| /*and supposedly |
| path->srcmRoute[i][j].sink |
| matches this speaker*/ |
| |
| outChnl = path->srcmRoute[i][j].outChnl; |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s pathID %d outChnl 0x%x inChnl 0x%x\n", |
| __func__, param.pathID, outChnl, |
| path->srcmRoute[i][j].inChnl); |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "mixInGain 0x%x, mixInGainR 0x%x\n", |
| mixInGain, mixInGainR); |
| |
| if (path->srcmRoute[i][j].outChnl == |
| CSL_CAPH_SRCM_STEREO_CH2_L |
| || path->srcmRoute[i][j].outChnl == |
| CSL_CAPH_SRCM_STEREO_CH2_R |
| ) { |
| /*mono output*/ |
| |
| if (path->srcmRoute[i][j].inChnl == |
| (int ) CAPH_SRCM_CH5 |
| || path->srcmRoute[i][j].inChnl |
| == (int) CAPH_SRCM_PASSCH1 |
| || path->srcmRoute[i][j].inChnl |
| ==( int ) CAPH_SRCM_PASSCH2) { |
| /*only on stereo inputs.*/ |
| if (mixInGain != GAIN_NA && |
| mixInGainR != GAIN_NA) { |
| mixInGain = |
| mixInGain-602; |
| mixInGainR = |
| mixInGainR-602; |
| } |
| } |
| } |
| |
| csl_srcmixer_setMixInGain( |
| path->srcmRoute[i][j].inChnl, |
| path->srcmRoute[i][j].outChnl, |
| mixInGain, mixInGainR); |
| csl_srcmixer_setMixBitSel( |
| outChnl, mixBitSel, mixBitSelR); |
| csl_srcmixer_setMixOutGain( |
| outChnl, mixOutGain, mixOutGainR); |
| } |
| } else { |
| aError( |
| "AUDDRV_SetAudioMode_Speaker can not find path\n"); |
| /*do not know which mix input to apply gain on |
| if (outChnl) |
| csl_srcmixer_setMixAllInGain(outChnl, |
| mixInGain, mixInGain); |
| */ |
| } |
| |
| if (path != 0) { |
| if (path->sink[0] == CSL_CAPH_DEV_DSP_throughMEM) |
| return; |
| /*no need for anything other than HW mixer gain for arm2sp */ |
| } |
| |
| /* Do not enable/disable sidetone path based on sysparm when in HW loopback */ |
| if (!param.inHWlpbk) { |
| /*Config sidetone */ |
| void *coef = NULL; |
| UInt16 gain = 0; |
| UInt16 enable = 0; |
| |
| enable = p->hw_sidetone_enable; |
| if (!enable) { |
| AUDDRV_HW_DisableSideTone(param.mode); |
| } else { |
| /*first step: enable sidetone */ |
| AUDDRV_HW_EnableSideTone(param.mode); |
| |
| /*second step: set filter and gain. */ |
| coef = (void *)&(p->hw_sidetone_eq[0]); |
| AUDDRV_HW_SetFilter(AUDDRV_SIDETONE_FILTER, coef); |
| |
| gain = p->hw_sidetone_gain; |
| csl_caph_audioh_sidetone_set_gain(gain); |
| } |
| } |
| |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetAudioMode_Mic |
| // |
| // Description: set audio mode. |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_SetAudioMode_Mic(AudioMode_t audio_mode, |
| AudioApp_t app, |
| unsigned int arg_pathID, |
| unsigned int arg_pathID2) |
| { |
| /* for 48 KHz recording no DSP and 8KHz recording through DSP. */ |
| |
| UInt16 gainTemp1 = 0, gainTemp2 = 0, gainTemp3 = 0, gainTemp4 = 0; |
| |
| #ifdef CONFIG_BCM_MODEM |
| SysAudioParm_t *p; |
| #else |
| AudioSysParm_t *p; |
| #endif |
| |
| p = &(AudParmP()[audio_mode + app * AUDIO_MODE_NUMBER]); |
| |
| /* Load the mic gains from sysparm. */ |
| |
| /*** |
| do not touch DSP UL gain in this function. |
| if(isDSPNeeded == TRUE) |
| { |
| dspULGain = 64; |
| //AudParmP()[mode].echoNlp_parms.echo_nlp_gain; |
| audio_control_generic( AUDDRV_CPCMD_SetBasebandUplinkGain, |
| dspULGain, 0, 0, 0, 0); |
| } |
| ***/ |
| |
| gainTemp1 = p->mic_pga; /* Q13p2 */ |
| csl_caph_audioh_setMicPga_by_mB(gainTemp1 * 25); |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s mode=%d, app=%d mic_gain %d\n", |
| __func__, audio_mode, app, gainTemp1*25); |
| |
| gainTemp1 = p->amic_dga_coarse_gain; /* Q13p2 dB */ |
| gainTemp2 = p->amic_dga_fine_gain; /* Q13p2 dB */ |
| |
| gainTemp1 = p->dmic1_dga_coarse_gain; |
| /* dmic1_dga_coarse_gain is the same register as amic_dga_coarse_gain */ |
| gainTemp2 = p->dmic1_dga_fine_gain; |
| |
| gainTemp3 = p->dmic2_dga_coarse_gain; |
| gainTemp4 = p->dmic2_dga_fine_gain; |
| |
| csl_caph_audioh_vin_set_cic_scale_by_mB(((int)gainTemp1) * 25, |
| ((int)gainTemp2) * 25, |
| ((int)gainTemp3) * 25, |
| ((int)gainTemp4) * 25); |
| |
| gainTemp1 = p->dmic3_dga_coarse_gain; |
| gainTemp2 = p->dmic3_dga_fine_gain; |
| gainTemp3 = p->dmic4_dga_coarse_gain; |
| gainTemp4 = p->dmic4_dga_fine_gain; |
| |
| csl_caph_audioh_nvin_set_cic_scale_by_mB(((int)gainTemp1) * 25, |
| ((int)gainTemp2) * 25, |
| ((int)gainTemp3) * 25, |
| ((int)gainTemp4) * 25); |
| |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_User_CtrlDSP |
| // |
| // Description: Control DSP Algo |
| // |
| //============================================================================= |
| */ |
| int AUDDRV_User_CtrlDSP(AudioDrvUserCtrl_t UserCtrlType, Boolean enable, |
| Int32 size, void *param) |
| { |
| #if defined(CONFIG_BCM_MODEM) |
| static Boolean ConfigSP = FALSE; |
| static void *spCtrl, *spVar; |
| |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_User_CtrlDSP"); |
| |
| switch (UserCtrlType) { |
| case AUDDRV_USER_SP_QUERY: |
| aTrace(LOG_AUDIO_DRIVER, "%s AUDDRV_USER_SP_QUERY", __func__); |
| |
| if (param == NULL) |
| return -EINVAL; |
| |
| csl_dsp_sp_query_msg((UInt32 *) param); |
| |
| break; |
| case AUDDRV_USER_SP_CTRL: |
| aTrace(LOG_AUDIO_DRIVER, "%s AUDDRV_USER_SP_CTRL", __func__); |
| |
| if (enable) { |
| if (size <= 0 || param == NULL) |
| return -EINVAL; |
| |
| if (spVar != NULL) |
| csl_dsp_sp_cnfg_msg((UInt16) enable, 0, 1, |
| (UInt32 *) param, spVar); |
| else { |
| spCtrl = kzalloc(size, GFP_KERNEL); |
| if (!spCtrl) |
| return -ENOMEM; |
| |
| memcpy(spCtrl, param, size); |
| ConfigSP = TRUE; |
| } |
| } else { |
| if (spVar != NULL) |
| kfree(spVar); |
| if (spCtrl != NULL) |
| kfree(spCtrl); |
| spVar = NULL; |
| spCtrl = NULL; |
| csl_dsp_sp_cnfg_msg((UInt16) enable, 0, 0, NULL, NULL); |
| } |
| break; |
| case AUDDRV_USER_SP_VAR: |
| aTrace(LOG_AUDIO_DRIVER, "%s AUDDRV_USER_SET_SP_VAR", |
| __func__); |
| |
| if (ConfigSP == TRUE && spCtrl != NULL) { |
| if (param == NULL) |
| return -EINVAL; |
| |
| csl_dsp_sp_cnfg_msg(1, 0, 1, spCtrl, |
| (UInt32 *) param); |
| ConfigSP = FALSE; |
| } else { |
| if (size <= 0 || param == NULL) |
| return -EINVAL; |
| |
| if (spVar == NULL) { |
| spVar = kzalloc(size, GFP_KERNEL); |
| if (!spVar) |
| return -ENOMEM; |
| memcpy(spVar, param, size); |
| } |
| csl_dsp_sp_ctrl_msg((UInt32 *) param); |
| } |
| |
| break; |
| case AUDDRV_USER_EQ_CTRL: |
| aTrace(LOG_AUDIO_DRIVER, "%s AUDDRV_USER_EQ_CTRL", __func__); |
| |
| if (enable == TRUE) { |
| if (param == NULL) |
| return -EINVAL; |
| |
| userEQOn = TRUE; |
| audio_cmf_filter((AudioCompfilter_t *) param); |
| } else |
| userEQOn = FALSE; |
| |
| break; |
| default: |
| aTrace(LOG_AUDIO_DRIVER, "%s Invalid request %d\n\r", |
| __func__, UserCtrlType); |
| break; |
| } |
| #else |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_User_CtrlDSP:dummy for AP only"); |
| #endif |
| return 0; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_User_HandleDSPInt |
| // |
| // Description: Handle DSP Interrupt |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_User_HandleDSPInt(UInt32 param1, UInt32 param2, UInt32 param3) |
| { |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_User_HandleDSPInt"); |
| if (sUserCB) |
| ((AUDDRV_User_CB) sUserCB) (param1, param2, param3); |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_ControlFlagFor_CustomGain |
| // |
| // Description: Set a flag to allow custom gain settings. |
| // If the flag is set the above three parameters are not set |
| // in AUDDRV_SetAudioMode( ) . |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_ControlFlagFor_CustomGain(Boolean on_off) |
| { |
| controlFlagForCustomGain = on_off; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_SetULSpeechRecordGain |
| // |
| // Description: set UL speech recording gain |
| // |
| //============================================================================= |
| */ |
| void AUDDRV_SetULSpeechRecordGain(Int16 gain) |
| { |
| audio_control_generic(AUDDRV_CPCMD_SetULSpeechRecordGain, |
| (UInt32) gain, 0, 0, 0, 0); |
| return; |
| } |
| |
| /****************************************************************************** |
| * |
| * Function Name: AUDDRV_SetTuningFlag |
| * |
| * Description: set Audio Tuning Flag |
| * |
| ******************************************************************************/ |
| void AUDDRV_SetTuningFlag(int flag) |
| { |
| audio_tuning_flag = flag; |
| } |
| |
| /****************************************************************************** |
| * |
| * Function Name: AUDDRV_TuningFlag |
| * |
| * Description: read Audio Tuning Flag |
| * |
| ******************************************************************************/ |
| int AUDDRV_TuningFlag(void) |
| { |
| return audio_tuning_flag; |
| } |
| |
| /*============================================================================= |
| // Private function prototypes |
| //============================================================================= |
| |
| //============================================================================= |
| // |
| // Function Name: AUDDRV_Telephony_InitHW |
| // |
| // Description: Enable the HW for Telephone voice call |
| // |
| //============================================================================= |
| */ |
| static void AUDDRV_Telephony_InitHW(AUDIO_SOURCE_Enum_t mic, |
| AUDIO_SINK_Enum_t speaker, |
| AUDIO_SAMPLING_RATE_t sample_rate, |
| Boolean bNeedDualMic) |
| { |
| CSL_CAPH_HWCTRL_CONFIG_t config; |
| UInt32 *memAddr = 0; |
| AUDIO_BITS_PER_SAMPLE_t bits = 24; |
| CSL_CAPH_PathID pathID; |
| |
| #if defined(ENABLE_BT16) |
| if (speaker == AUDIO_SINK_BTM) |
| bits = 16; |
| #endif |
| |
| aTrace(LOG_AUDIO_DRIVER, "%s mic=%d, spkr=%d sample_rate=%u*\n", |
| __func__, mic, speaker, sample_rate); |
| |
| memset(&config, 0, sizeof(CSL_CAPH_HWCTRL_CONFIG_t)); |
| |
| telephonyPathID.ulPathID = 0; |
| telephonyPathID.ul2PathID = 0; |
| telephonyPathID.dlPathID = 0; |
| |
| /* DL */ |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = 0; |
| config.source = CSL_CAPH_DEV_DSP; |
| config.sink = AUDDRV_GetDRVDeviceFromSpkr(speaker); |
| config.dmaCH = CSL_CAPH_DMA_NONE; |
| /*If DSP DL goes to IHF, Sample rate should be 48KHz. */ |
| if (speaker == AUDIO_SINK_LOUDSPK) { |
| config.source = CSL_CAPH_DEV_DSP_throughMEM; |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_48000; |
| } else { |
| config.src_sampleRate = sample_rate; |
| } |
| config.snk_sampleRate = AUDIO_SAMPLING_RATE_48000; |
| |
| if (config.sink == CSL_CAPH_DEV_HS) |
| config.chnlNum = AUDIO_CHANNEL_STEREO; |
| else |
| config.chnlNum = AUDIO_CHANNEL_MONO; |
| |
| config.bitPerSample = bits; |
| |
| sink = config.sink; |
| if (sink == CSL_CAPH_DEV_IHF) { |
| memAddr = AUDIO_GetIHF48KHzBufferBaseAddress(); |
| |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_48000; |
| config.source = CSL_CAPH_DEV_DSP_throughMEM; |
| /* csl_caph_EnablePath() handles the case DSP_MEM |
| when sink is IHF */ |
| |
| csl_caph_hwctrl_setDSPSharedMemForIHF((UInt32) memAddr); |
| } else { |
| config.source = CSL_CAPH_DEV_DSP; |
| } |
| |
| telephonyPathID.dlPathID = csl_caph_hwctrl_EnablePath(config); |
| |
| |
| /* UL */ |
| pathID = csl_caph_FindPathID(CSL_CAPH_DEV_DSP, |
| AUDDRV_GetDRVDeviceFromMic(mic), 0); |
| if (pathID) { |
| /* If voice recording is ongoing, no need to set up UL path. |
| * Unable to handle this case: record and call use different |
| * mics. |
| */ |
| aTrace(LOG_AUDIO_DRIVER, "%s UL path %d exists\n", |
| __func__, pathID); |
| AUDDRV_DisableDSPInput(0); |
| /*do not set ulPathID before AUDDRV_DisableDSPInput*/ |
| telephonyPathID.ulPathID = pathID; |
| } |
| |
| /* Secondary mic */ |
| /* If Dual Mic is enabled. Theoretically DMIC3 or DMIC4 are used*/ |
| if (bNeedDualMic) { |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = 0; |
| config.source = DUALMICS_NOISE_REF_MIC; |
| config.sink = CSL_CAPH_DEV_DSP; |
| config.dmaCH = CSL_CAPH_DMA_NONE; |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_48000; |
| config.snk_sampleRate = sample_rate; |
| config.chnlNum = AUDIO_CHANNEL_MONO; |
| config.bitPerSample = bits; |
| |
| telephonyPathID.ul2PathID = csl_caph_hwctrl_EnablePath(config); |
| } |
| |
| /* Primary mic */ |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = 0; |
| config.source = AUDDRV_GetDRVDeviceFromMic(mic); |
| config.sink = CSL_CAPH_DEV_DSP; |
| config.dmaCH = CSL_CAPH_DMA_NONE; |
| config.src_sampleRate = AUDIO_SAMPLING_RATE_48000; |
| config.snk_sampleRate = sample_rate; |
| config.chnlNum = AUDIO_CHANNEL_MONO; |
| config.bitPerSample = bits; |
| |
| if (voiceRecOn && voiceInMic != mic) |
| aError("%s voice record (%d) and call (%d) different mics\n", |
| __func__, voiceInMic, mic); |
| if (!pathID) |
| telephonyPathID.ulPathID = csl_caph_hwctrl_EnablePath(config); |
| |
| return; |
| } |
| |
| /*============================================================================= |
| // |
| // Function Name: AUDDRV_Telephony_DeinitHW |
| // |
| // Description: Disable the HW for Telephone voice call |
| // |
| //============================================================================= |
| */ |
| static void AUDDRV_Telephony_DeinitHW(void) |
| { |
| CSL_CAPH_HWCTRL_CONFIG_t config; |
| aTrace(LOG_AUDIO_DRIVER, "AUDDRV_Telephony_DeinitHW\n"); |
| |
| memset(&config, 0, sizeof(CSL_CAPH_HWCTRL_CONFIG_t)); |
| |
| AUDDRV_HW_DisableSideTone(AUDCTRL_GetAudioMode()); |
| |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = telephonyPathID.ulPathID; |
| |
| if (!voiceRecOn) |
| csl_caph_hwctrl_DisablePath(config); |
| |
| if (telephonyPathID.ul2PathID != 0) { |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = telephonyPathID.ul2PathID; |
| |
| (void)csl_caph_hwctrl_DisablePath(config); |
| } |
| |
| config.streamID = CSL_CAPH_STREAM_NONE; |
| config.pathID = telephonyPathID.dlPathID; |
| |
| (void)csl_caph_hwctrl_DisablePath(config); |
| |
| sink = CSL_CAPH_DEV_NONE; |
| |
| telephonyPathID.ulPathID = 0; |
| telephonyPathID.ul2PathID = 0; |
| telephonyPathID.dlPathID = 0; |
| |
| return; |
| } |
| |
| /**************************************************************************** |
| * |
| * Function Name: AUDDRV_HW_SetFilter(AUDDRV_HWCTRL_FILTER_e filter, |
| * void* coeff) |
| * |
| * Description: Load filter coefficients |
| * |
| ****************************************************************************/ |
| static void AUDDRV_HW_SetFilter(AUDDRV_HWCTRL_FILTER_e filter, |
| void *coeff) |
| { |
| if (filter == AUDDRV_SIDETONE_FILTER) |
| csl_caph_audioh_sidetone_load_filter((UInt32 *) coeff); |
| } |
| |
| /**************************************************************************** |
| * |
| * Function Name: AUDDRV_HW_EnableSideTone(AudioMode_t audio_mode) |
| * |
| * Description: Enable Sidetone path |
| * |
| ****************************************************************************/ |
| static void AUDDRV_HW_EnableSideTone(AudioMode_t audio_mode) |
| { |
| AUDDRV_PATH_Enum_t pathId = AUDDRV_PATH_VIBRA_OUTPUT; |
| switch (audio_mode) { |
| case AUDIO_MODE_HEADSET: |
| case AUDIO_MODE_TTY: |
| pathId = AUDDRV_PATH_HEADSET_OUTPUT; |
| break; |
| case AUDIO_MODE_HANDSET: |
| case AUDIO_MODE_HAC: |
| pathId = AUDDRV_PATH_EARPICEC_OUTPUT; |
| break; |
| case AUDIO_MODE_SPEAKERPHONE: |
| pathId = AUDDRV_PATH_IHF_OUTPUT; |
| break; |
| |
| default: |
| ; |
| } |
| csl_caph_audioh_sidetone_control((int)pathId, TRUE); |
| } |
| |
| /**************************************************************************** |
| * |
| * Function Name: AUDDRV_HW_DisableSideTone(AudioMode_t audio_mode) |
| * |
| * Description: Disable Sidetone path |
| * |
| ****************************************************************************/ |
| static void AUDDRV_HW_DisableSideTone(AudioMode_t audio_mode) |
| { |
| AUDDRV_PATH_Enum_t pathId = AUDDRV_PATH_VIBRA_OUTPUT; |
| switch (audio_mode) { |
| case AUDIO_MODE_HEADSET: |
| case AUDIO_MODE_TTY: |
| pathId = AUDDRV_PATH_HEADSET_OUTPUT; |
| break; |
| case AUDIO_MODE_HANDSET: |
| case AUDIO_MODE_HAC: |
| pathId = AUDDRV_PATH_EARPICEC_OUTPUT; |
| break; |
| case AUDIO_MODE_SPEAKERPHONE: |
| pathId = AUDDRV_PATH_IHF_OUTPUT; |
| break; |
| |
| default: |
| ; |
| } |
| csl_caph_audioh_sidetone_control((int)pathId, FALSE); |
| } |
| |
| |
| /*========================================================================== |
| // |
| // Function Name: AUDDRV_GetDRVDeviceFromMic |
| // |
| // Description: Get the audio driver Device from the Microphone selection. |
| // |
| // ========================================================================= |
| */ |
| static CSL_CAPH_DEVICE_e AUDDRV_GetDRVDeviceFromMic(AUDIO_SOURCE_Enum_t mic) |
| { |
| CSL_CAPH_DEVICE_e dev = CSL_CAPH_DEV_NONE; |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "AUDDRV_GetDRVDeviceFromMic:: mic = 0x%x\n", mic); |
| |
| switch (mic) { |
| case AUDIO_SOURCE_UNDEFINED: |
| dev = CSL_CAPH_DEV_NONE; |
| break; |
| |
| case AUDIO_SOURCE_SPEECH_DIGI: |
| /*case AUDDRV_DUAL_MIC_DIGI12: |
| //case AUDDRV_DUAL_MIC_DIGI21: */ |
| dev = CSL_CAPH_DEV_DIGI_MIC; |
| break; |
| |
| case AUDIO_SOURCE_DIGI1: |
| dev = CSL_CAPH_DEV_DIGI_MIC_L; |
| break; |
| |
| case AUDIO_SOURCE_DIGI2: |
| dev = CSL_CAPH_DEV_DIGI_MIC_R; |
| break; |
| |
| case AUDIO_SOURCE_ANALOG_MAIN: |
| dev = CSL_CAPH_DEV_ANALOG_MIC; |
| break; |
| |
| case AUDIO_SOURCE_ANALOG_AUX: |
| dev = CSL_CAPH_DEV_HS_MIC; |
| break; |
| |
| case AUDIO_SOURCE_BTM: |
| dev = CSL_CAPH_DEV_BT_MIC; |
| break; |
| |
| case AUDIO_SOURCE_USB: |
| dev = CSL_CAPH_DEV_MEMORY; |
| break; |
| |
| default: |
| break; |
| }; |
| |
| return dev; |
| } |
| |
| /*========================================================================== |
| // |
| // Function Name: AUDDRV_GetDRVDeviceFromSpkr |
| // |
| // Description: Get the audio driver Device from the Speaker selection. |
| // |
| // ========================================================================= |
| */ |
| static CSL_CAPH_DEVICE_e AUDDRV_GetDRVDeviceFromSpkr(AUDIO_SINK_Enum_t spkr) |
| { |
| CSL_CAPH_DEVICE_e dev = CSL_CAPH_DEV_NONE; |
| |
| aTrace(LOG_AUDIO_DRIVER, |
| "AUDDRV_GetDRVDeviceFromSpkr:: spkr = 0x%x\n", spkr); |
| |
| switch (spkr) { |
| case AUDIO_SINK_UNDEFINED: |
| dev = CSL_CAPH_DEV_NONE; |
| break; |
| |
| case AUDIO_SINK_HANDSET: |
| dev = CSL_CAPH_DEV_EP; |
| break; |
| |
| case AUDIO_SINK_LOUDSPK: |
| dev = CSL_CAPH_DEV_IHF; |
| break; |
| |
| case AUDIO_SINK_HEADSET: |
| dev = CSL_CAPH_DEV_HS; |
| break; |
| |
| case AUDIO_SINK_VIBRA: |
| dev = CSL_CAPH_DEV_VIBRA; |
| break; |
| |
| case AUDIO_SINK_BTM: |
| dev = CSL_CAPH_DEV_BT_SPKR; |
| break; |
| |
| case AUDIO_SINK_USB: |
| dev = CSL_CAPH_DEV_MEMORY; |
| break; |
| |
| default: |
| break; |
| }; |
| |
| return dev; |
| } |
| |
| static UInt32 *AUDIO_GetIHF48KHzBufferBaseAddress(void) |
| { |
| /* special path for IHF voice call |
| need to use the physical address |
| // Linux only change |
| AP_SharedMem_t *ap_shared_mem_ptr = |
| ioremap_nocache(AP_SH_BASE, AP_SH_SIZE); |
| // Linux only : to get the physical address use the virtual |
| address to compute offset and |
| // add to the base address |
| UInt32 *memAddr = (UInt32 *)(AP_SH_BASE + |
| ((UInt32)&(ap_shared_mem_ptr->shared_aud_out_buf_48k[0][0]) - |
| (UInt32)ap_shared_mem_ptr)); |
| |
| return memAddr; |
| */ |
| return AUDIO_Return_IHF_48kHz_buffer_base_address(); |
| |
| } |
| |
| static void AP_ProcessAudioEnableDone(UInt16 enabled_path) |
| { |
| aTrace(LOG_AUDIO_DRIVER, |
| "AP_ProcessAudioEnableDone, Got AUDIO ENABLE RESP FROM DSP 0x%x\n", |
| enabled_path); |
| |
| csl_caph_dspcb(enabled_path & ~((UInt16)DSP_AADMAC_RETIRE_DS_CMD)); |
| |
| complete(&audioEnableDone); |
| } |
| |
| #if defined(CONFIG_RHEA_PANDA) |
| static void AP_ProcessExtModemCallDone(UInt16 enabled_path) |
| { |
| aTrace(LOG_AUDIO_DRIVER, |
| "%s, Got ExtModemCall RESP FROM DSP\n", __func__); |
| |
| if (enabled_path) |
| csl_caph_hwctrl_extModem_StartPath_step2( |
| ulExtModemPathID, dlExtModemPathID); |
| else |
| csl_caph_hwctrl_extModem_StopPath_step1( |
| ulExtModemPathID, dlExtModemPathID); |
| |
| /* can proceed */ |
| complete(&extModemCallDone); |
| |
| } |
| #endif |
| |
| /**************************************************************************** |
| * |
| * Function Name: AUDDRV_GetULPath |
| * |
| * Description: Get UL path |
| * |
| *****************************************************************************/ |
| int AUDDRV_GetULPath(void) |
| { |
| int ret = (int)telephonyPathID.ulPathID; |
| aTrace(LOG_AUDIO_DRIVER, "%s %d\n", __func__, ret); |
| return ret; |
| } |
| |
| void AUDDRV_SetCallMode(Int32 callMode) |
| { |
| curCallMode = callMode; |
| aTrace(LOG_AUDIO_DRIVER, "%s callMode = %d\n", |
| __func__, (int)curCallMode); |
| } |
| |
| void AUDDRV_CPResetCleanup(void) |
| { |
| currVoiceMic = AUDIO_SOURCE_UNDEFINED; |
| currVoiceSpkr = AUDIO_SINK_UNDEFINED; |
| voiceRecOn = FALSE; |
| voicePlayOutpathEnabled = FALSE; |
| dspECEnable = TRUE; |
| dspNSEnable = TRUE; |
| inCallRateChange = FALSE; |
| sink = CSL_CAPH_DEV_NONE; |
| telephonyPathID.ulPathID = 0; |
| telephonyPathID.ul2PathID = 0; |
| telephonyPathID.dlPathID = 0; |
| voiceInMic = AUDIO_SOURCE_UNDEFINED; |
| voiceInSr = 0; |
| curCallMode = CALL_MODE_NONE; |
| init_completion(&audioEnableDone); |
| } |