blob: e06cbaaf14bfd9f43869c5ba975e72bc01a6ca97 [file] [log] [blame]
/*****************************************************************************
Copyright 2010-2012 Broadcom Corporation. All rights reserved.
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, available at
http://www.gnu.org/copyleft/gpl.html (the "GPL").
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.
*****************************************************************************/
/*
*
*****************************************************************************
*
* audio_caph.c
*
* PURPOSE:
*
* Serialize audio control operation
* Eliminate waits in audio control because of atomic operation
* requirement from ALSA
*
* NOTES:
*
*****************************************************************************/
/* ---- Include Files ---------------------------------------------------- */
#include <linux/version.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <mach/cpu.h>
#include <plat/pi_mgr.h>
#include "mobcom_types.h"
#include "resultcode.h"
#include "audio_consts.h"
#include "ossemaphore.h"
#include "bcm_fuse_sysparm_CIB.h"
#include "csl_caph.h"
#include "audio_vdriver.h"
#include "audio_controller.h"
#include "audio_ddriver.h"
#include "audio_caph.h"
#include "caph_common.h"
#include "audio_trace.h"
#ifdef CONFIG_ARCH_JAVA
#include <linux/slab.h>
static struct workqueue_struct *pWorkqueue_AudioControl;
#define TIMEOUT_STOP_REQ_MS 300000
#ifdef CONFIG_SMP
#define QUEUE_WORK(x, y) queue_work(x, \
(struct work_struct *)y);
#else
#define QUEUE_WORK(x, y) queue_work_on(0, x, \
(struct work_struct *)y);
#endif
#endif
#define USE_HR_TIMER
/* #define USE_HUBCLK_AUTOGATE_WORKAROUND */
/* for unknown reason, aadmac autogate bit
was set and leads to mute on Rhea. enable
this flag to report error when it is set */
#define CHECK_AADMAC_AUTOGATE_STATUS
#ifdef USE_HR_TIMER
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#define MS_TO_NS(x) (x * 1E6L)
static struct hrtimer hr_timer;
static ktime_t ktime;
#endif
/* ---- Data structure ------------------------------------------------- */
/**
* Wrap up HAL_AUDIO_Ctrl parameters
* The record is passed to worker thread via KFIFO
*
*/
struct _TMsgBrcmAudioCtrl {
#ifdef CONFIG_ARCH_JAVA
struct work_struct mwork;
struct completion comp;
bool timeout;
#endif
BRCM_AUDIO_ACTION_en_t action_code;
BRCM_AUDIO_Control_Params_un_t param;
void *pCallBack;
int block;
};
#define TMsgAudioCtrl struct _TMsgBrcmAudioCtrl
#ifndef CONFIG_ARCH_JAVA
/**
* The thread private data structure
*/
struct TAudioHalThreadData {
/*
* KFIFO to pass control parameters from audio HAL caller to
* worker thread
*/
struct kfifo m_pkfifo;
/*
* spin lock to protect KFIFO access so that audio HAL can
* accept concurrent caller
*/
spinlock_t m_lock;
/* worker thread data structure */
struct work_struct mwork;
struct workqueue_struct *pWorkqueue_AudioControl;
Semaphore_t action_complete;
struct kfifo m_pkfifo_out;
spinlock_t m_lock_out;
};
#endif
/*voice rec qos node to conrol ARM core idle*/
static struct pi_mgr_qos_node voice_recorder_qos_node;
static bool voice_qos_state;
#if 0
static char action_names[ACTION_AUD_TOTAL][40] = {
"OpenPlay",
"ClosePlay",
"StartPlay",
"StopPlay",
"PausePlay",
"ResumePlay",
"StartRecord",
"StopRecord",
"OpenRecord",
"CloseRecord",
"SetPrePareParameters",/* 10 */
"AddChannel",
"RemoveChannel",
"EnableTelephony",
"DisableTelephony",
"EnableECNSTelephony",
"DisableECNSTelephony",
"SetTelephonyMicSpkr",
"MutePlayback",
"MuteRecord",
"MuteTelephony",/* 20 */
"EnableByPassVibra",
"DisableByPassVibra",
"SetPlaybackVolume",
"SetRecordGain",
"SetTelephonySpkrVolume",
"SwitchSpkr",
"SetHWLoopback",
"SetAudioMode",
"SetAudioApp", /*set audio profile*/
"EnableFMPlay",
"DisableFMPlay",
"SetARM2SPInst",
"RateChange", /*33 */
"AmpEnable",
"DisableByPassVibra_CB",
"SetCallMode",
"ConnectDL",
"UpdateUserVolSetting",
"BufferReady",
"AtCtl",
};
#endif
static unsigned int pathID[CTL_STREAM_PANEL_LAST];
static int telephonyIsEnabled;
#ifdef CONFIG_ARCH_JAVA
static void AUDIO_Ctrl_Process(TMsgAudioCtrl *msgAudioCtrl);
#else
static unsigned int n_msg_in, n_msg_out, last_action;
static struct completion complete_kfifo;
static struct TAudioHalThreadData sgThreadData;
static DEFINE_MUTEX(mutexBlock);
#define KFIFO_SIZE 2048
#define BLOCK_WAITTIME_MS 60000
#define KFIFO_TIMEOUT_MS 60000
static void AUDIO_Ctrl_Process(BRCM_AUDIO_ACTION_en_t action_code,
void *arg_param, void *callback, int block);
#endif
#ifdef CONFIG_AUDIO_S2
static unsigned int pcm_vibra_path_id;
static AUDIO_DRIVER_HANDLE_t pcm_vibra_drv_handle;
static spinlock_t vibra_drv_lock;
static UInt8 *s_vibra_dma_bufp;
static int s_vibra_strength;
#define VIBRA_STRENGTH_RANGE 125 /* -125 ~ 125*/
#define VIBRA_PERIOD_BYTES 480 /*5ms*/
static void PCM_Vibra_Gen_Start(Int32 strength);
static void PCM_Vibra_Gen_Stop(void);
#endif
#ifdef USE_HR_TIMER
static enum hrtimer_restart TimerCbStopVibrator(struct hrtimer *timer)
{
Result_t status = AUDIO_Ctrl_Trigger(ACTION_AUD_DisableByPassVibra_CB,
NULL, NULL, 0);
if (status != RESULT_OK) {
/*recur after 100ms */
hrtimer_forward_now(timer, ktime_set(0, (100 * 1000000)));
return HRTIMER_RESTART;
} else
aTrace(LOG_AUDIO_CNTLR, "Disable Vib from HR Timer cb\n");
return HRTIMER_NORESTART;
}
#else
static struct timer_list gTimerVib;
static struct timer_list *gpVibratorTimer;
void TimerCbStopVibrator(unsigned long priv)
{
AUDIO_Ctrl_Trigger(ACTION_AUD_DisableByPassVibra, NULL, NULL, 0);
/* AUDCTRL_DisableBypassVibra(); */
aTrace(LOG_AUDIO_CNTLR, "Disable Vib from timer cb\n");
}
#endif
/**
* AudioCtrlWorkThread: Worker thread, it query KFIFO for operation message
* and call HAL_AudioProcess.
*
* @work: work structure
*/
static void AudioCtrlWorkThread(struct work_struct *work)
{
#ifdef CONFIG_ARCH_JAVA
TMsgAudioCtrl *msgAudioCtrl = container_of(work, TMsgAudioCtrl, mwork);
#else
TMsgAudioCtrl msgAudioCtrl;
unsigned int len = 0;
while (1) {
/* get operation code from fifo */
len = kfifo_out_locked(&sgThreadData.m_pkfifo,
(unsigned char *)&msgAudioCtrl,
sizeof(TMsgAudioCtrl),
&sgThreadData.m_lock);
/* Commenting debug prints to eliminate compilation errors for
* kfifo member accesses
*/
/*
* if( (len != sizeof(TMsgAudioCtrl)) && (len!=0) )
* DEBUG("Error AUDIO_Ctrl len=%d expected %d
* in=%d, out=%d\n", len, sizeof(TMsgAudioCtrl),
* sgThreadData.m_pkfifo.in, sgThreadData.m_pkfifo.out);
*/
if (len == 0) /* FIFO empty sleep */
return;
if (completion_done(&complete_kfifo) == 0) {
aTrace(LOG_AUDIO_CNTLR, "Sending complete");
complete(&complete_kfifo);
}
n_msg_in++;
last_action = msgAudioCtrl.action_code;
#endif
#if defined(CONFIG_BCM_MODEM)
if (is_dsp_timeout())
return;
#endif
#ifdef CONFIG_ARCH_JAVA
/* process the operation */
AUDIO_Ctrl_Process(msgAudioCtrl);
if ((msgAudioCtrl && msgAudioCtrl->block != 1)
|| (msgAudioCtrl->timeout)) {
kfree(msgAudioCtrl);
return;
}
if (msgAudioCtrl->block == 1)
complete(&msgAudioCtrl->comp);
#else
/* process the operation */
AUDIO_Ctrl_Process(msgAudioCtrl.action_code,
&msgAudioCtrl.param,
msgAudioCtrl.pCallBack, msgAudioCtrl.block);
n_msg_out++;
}
#endif
return;
}
/**
* AudioCodecIdHander :callback function that handles the rate change
*
*/
static void AudioCodecIdHander(int codecID)
{
BRCM_AUDIO_Param_RateChange_t param_rate_change;
aTrace(LOG_AUDIO_CNTLR,
"AudioCodeCIdHander : CodecId = %d \r\n", codecID);
param_rate_change.codecID = codecID;
AUDIO_Ctrl_Trigger(ACTION_AUD_RateChange, &param_rate_change, NULL, 0);
}
/**
* CPResetHandler :callback function that handles CP reset
*
*/
static void CPResetHandler(Boolean cp_reset)
{
BRCM_AUDIO_Param_cpReset_t parm_cpReset;
aTrace(LOG_AUDIO_CNTLR, "CPResetHandler\r\n");
parm_cpReset.cp_reset_start = cp_reset;
AUDIO_Ctrl_Trigger(ACTION_AUD_HandleCPReset, &parm_cpReset, NULL, 0);
}
/**
* caph_audio_init: registers callback for handling rate change and
* if any init required.
*
*/
void caph_audio_init(void)
{
int result;
AUDDRV_RegisterRateChangeCallback(AudioCodecIdHander);
AUDDRV_RegisterHandleCPResetCB(CPResetHandler);
/*request a QOS node for voice rec*/
result = pi_mgr_qos_add_request(&voice_recorder_qos_node,
"voice_recorder_qos", PI_MGR_PI_ID_ARM_CORE,
PI_MGR_QOS_DEFAULT_VALUE);
if (result) {
aError("Voice Rec QOS node req failed\n");
voice_qos_state = FALSE;
}
else
voice_qos_state = TRUE;
#ifndef CONFIG_ARCH_JAVA
init_completion(&complete_kfifo);
#endif
#if defined(CONFIG_BCM_MODEM)
set_flag_dsp_timeout(0);
#endif
#ifdef CONFIG_AUDIO_S2
spin_lock_init(&vibra_drv_lock);
#endif
#ifdef USE_HR_TIMER
hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hr_timer.function = &TimerCbStopVibrator;
#endif
}
/**
* LaunchAudioHalThread: Create Worker thread.
*
*/
int LaunchAudioCtrlThread(void)
{
int ret = 0;
#ifdef CONFIG_ARCH_JAVA
pWorkqueue_AudioControl = alloc_ordered_workqueue(
"AudioCtrlWq", WQ_MEM_RECLAIM);
if (!pWorkqueue_AudioControl) {
#else
spin_lock_init(&sgThreadData.m_lock);
spin_lock_init(&sgThreadData.m_lock_out);
ret = kfifo_alloc(&sgThreadData.m_pkfifo, KFIFO_SIZE, GFP_KERNEL);
/*
* Commenting debug prints to eliminate compilation errors for kfifo
* member access
*/
/*
* DEBUG("LaunchAudioCtrlThread KFIFO_SIZE= %d actual =%d\n",
* KFIFO_SIZE,sgThreadData.m_pkfifo.size);
*/
ret = kfifo_alloc(&sgThreadData.m_pkfifo_out, KFIFO_SIZE, GFP_KERNEL);
/*
* Commenting debug prints to eliminate compilation errors for kfifo
* member access
*/
/*
* DEBUG("LaunchAudioCtrlThread KFIFO_SIZE= %d actual =%d\n",
* KFIFO_SIZE,sgThreadData.m_pkfifo_out.size);
*/
sgThreadData.action_complete = OSSEMAPHORE_Create(0, 0);
INIT_WORK(&sgThreadData.mwork, AudioCtrlWorkThread);
sgThreadData.pWorkqueue_AudioControl = alloc_ordered_workqueue(
"AudioCtrlWq", WQ_MEM_RECLAIM);
if (!sgThreadData.pWorkqueue_AudioControl) {
#endif
aError("\n Error : Can not create work queue:AudioCtrlWq\n");
return -1;
}
#ifndef USE_HR_TIMER
gpVibratorTimer = NULL;
#endif
return ret;
}
/**
* LaunchAudioHalThread: Clean up, free KFIFO
*
*/
int TerminateAudioHalThread(void)
{
#ifdef CONFIG_ARCH_JAVA
if (pWorkqueue_AudioControl) {
flush_workqueue(pWorkqueue_AudioControl);
destroy_workqueue(pWorkqueue_AudioControl);
}
#else
if (sgThreadData.pWorkqueue_AudioControl) {
flush_workqueue(sgThreadData.pWorkqueue_AudioControl);
destroy_workqueue(sgThreadData.pWorkqueue_AudioControl);
}
kfifo_free(&sgThreadData.m_pkfifo);
kfifo_free(&sgThreadData.m_pkfifo_out);
#endif
return 0;
}
/*
* this is to avoid coverity error: CID 17571:
* Out-of-bounds access (OVERRUN_STATIC)Overrunning struct type
* BRCM_AUDIO_Param_Close_t (and other structures) of size 16 bytes by passing
* it as an argument to a function which indexes it at byte position 103.
*/
static int AUDIO_Ctrl_Trigger_GetParamsSize(BRCM_AUDIO_ACTION_en_t action_code)
{
int size = 0;
switch (action_code) {
case ACTION_AUD_OpenRecord:
case ACTION_AUD_OpenPlay:
case ACTION_AUD_OpenVoIP:
size = sizeof(BRCM_AUDIO_Param_Open_t);
break;
case ACTION_AUD_CloseRecord:
case ACTION_AUD_ClosePlay:
case ACTION_AUD_CloseVoIP:
size = sizeof(BRCM_AUDIO_Param_Close_t);
break;
case ACTION_AUD_StartRecord:
case ACTION_AUD_StartPlay:
case ACTION_AUD_StartVoIP:
size = sizeof(BRCM_AUDIO_Param_Start_t);
break;
case ACTION_AUD_StopRecord:
case ACTION_AUD_StopPlay:
case ACTION_AUD_StopVoIP:
size = sizeof(BRCM_AUDIO_Param_Stop_t);
break;
case ACTION_AUD_PausePlay:
size = sizeof(BRCM_AUDIO_Param_Pause_t);
break;
case ACTION_AUD_ResumePlay:
size = sizeof(BRCM_AUDIO_Param_Resume_t);
break;
case ACTION_AUD_SetPrePareParameters:
case ACTION_AUD_SET_VOIP_UL_CB:
case ACTION_AUD_SET_VOIP_DL_CB:
size = sizeof(BRCM_AUDIO_Param_Prepare_t);
break;
case ACTION_AUD_BufferReady:
size = sizeof(BRCM_AUDIO_Param_BufferReady_t);
break;
case ACTION_AUD_AddChannel:
case ACTION_AUD_RemoveChannel:
case ACTION_AUD_SwitchSpkr:
size = sizeof(BRCM_AUDIO_Param_Spkr_t);
break;
case ACTION_AUD_EnableTelephony:
case ACTION_AUD_DisableTelephony:
case ACTION_AUD_SetTelephonyMicSpkr:
size = sizeof(BRCM_AUDIO_Param_Call_t);
break;
case ACTION_AUD_MutePlayback:
case ACTION_AUD_MuteRecord:
case ACTION_AUD_MuteTelephony:
size = sizeof(BRCM_AUDIO_Param_Mute_t);
break;
case ACTION_AUD_EnableECNSTelephony:
case ACTION_AUD_DisableECNSTelephony:
size = sizeof(BRCM_AUDIO_Param_ECNS_t);
break;
case ACTION_AUD_EnableByPassVibra:
size = sizeof(BRCM_AUDIO_Param_Vibra_t);
break;
case ACTION_AUD_DisableByPassVibra:
size = 0;
break;
case ACTION_AUD_SetPlaybackVolume:
case ACTION_AUD_SetRecordGain:
case ACTION_AUD_SetTelephonySpkrVolume:
case ACTION_AUD_UpdateUserVolSetting:
size = sizeof(BRCM_AUDIO_Param_Volume_t);
break;
case ACTION_AUD_SetHWLoopback:
size = sizeof(BRCM_AUDIO_Param_Loopback_t);
break;
case ACTION_AUD_SetAudioMode:
size = sizeof(BRCM_AUDIO_Param_SetMode_t);
break;
case ACTION_AUD_EnableFMPlay:
case ACTION_AUD_DisableFMPlay:
case ACTION_AUD_SetARM2SPInst:
size = sizeof(BRCM_AUDIO_Param_FM_t);
break;
case ACTION_AUD_RateChange:
size = sizeof(BRCM_AUDIO_Param_RateChange_t);
break;
case ACTION_AUD_SetAudioApp:
case ACTION_AUD_RemoveAudioApp:
size = sizeof(BRCM_AUDIO_Param_SetApp_t);
break;
case ACTION_AUD_AMPEnable:
size = sizeof(BRCM_AUDIO_Param_AMPCTL_t);
break;
case ACTION_AUD_SetCallMode:
size = sizeof(BRCM_AUDIO_Param_CallMode_t);
break;
case ACTION_AUD_HandleCPReset:
size = sizeof(BRCM_AUDIO_Param_cpReset_t);
break;
case ACTION_AUD_BTTest:
size = sizeof(BRCM_AUDIO_Param_BT_Test_t);
break;
case ACTION_AUD_CfgIHF:
size = sizeof(BRCM_AUDIO_Param_Cfg_IHF_t);
break;
case ACTION_AUD_CfgSSP:
size = sizeof(BRCM_AUDIO_Param_Cfg_SSP_t);
break;
case ACTION_AUD_HwCtl:
size = sizeof(BRCM_AUDIO_Param_HwCtl_t);
break;
case ACTION_AUD_AtCtl:
size = sizeof(BRCM_AUDIO_Param_AtCtl_t);
break;
default:
break;
}
return size;
}
/**
* AUDIO_Ctrl_Trigger
* Client call this function to execute audio HAL functions.
* This function forward the message to worker thread to do actual work
* @action_code: action request enum
* @arg_param: argument for the action request
* @callback: callback function pointer,
* see typedef void (*PFuncAudioCtrlCB)(int)
* @block: bit 0 to indicate blocking call or not
* It is also used as private data for the call back function if callback
* is specified.
* The caller will get called as callback(block)
* When used as private data for the call back function, please pass
* a pointer which is 4 bytes alignment (block&0x03 ==0 ), because we
* we reserve bit 0 to indicate block mode.
*
* Return 0 for success, non-zero for error code
*/
#ifdef CONFIG_ARCH_JAVA
Result_t AUDIO_Ctrl_Trigger(BRCM_AUDIO_ACTION_en_t action_code,
void *arg_param, void *callback, int block)
{
TMsgAudioCtrl *msgAudioCtrl = NULL;
Result_t status = RESULT_OK;
static int record48K_in_call_is_blocked;
int params_size = 0;
long ret = 0;
#if defined(CONFIG_BCM_MODEM)
if (is_dsp_timeout())
return RESULT_OK;
#endif
if (action_code < ACTION_AUD_OpenPlay
|| action_code >= ACTION_AUD_TOTAL) {
aWarn("AUDIO_Ctrl_Trigger: Not a Valid action code: %d",
action_code);
return RESULT_ERROR;
}
if (action_code == ACTION_AUD_StartPlay ||
action_code == ACTION_AUD_StopPlay ||
action_code == ACTION_AUD_PausePlay ||
action_code == ACTION_AUD_ResumePlay ||
action_code == ACTION_AUD_StartRecord ||
action_code == ACTION_AUD_StopRecord ||
action_code == ACTION_AUD_RateChange ||
action_code == ACTION_AUD_AddChannel ||
action_code == ACTION_AUD_RemoveChannel)
msgAudioCtrl = (TMsgAudioCtrl *)
kzalloc(sizeof(TMsgAudioCtrl), GFP_ATOMIC);
else
msgAudioCtrl = (TMsgAudioCtrl *)
kzalloc(sizeof(TMsgAudioCtrl), GFP_KERNEL);
if (!msgAudioCtrl) {
aError(
"Unable to allocate memory"
"for workqueue action_code = %d!!!\n",
action_code);
return RESULT_ERROR;
}
/** BEGIN: not support 48KHz recording during voice call */
if (action_code == ACTION_AUD_StartRecord) {
BRCM_AUDIO_Param_Start_t param_start;
memcpy((void *)&param_start, arg_param,
sizeof(BRCM_AUDIO_Param_Start_t));
if (param_start.callMode == MODEM_CALL
&& param_start.rate == AUDIO_SAMPLING_RATE_48000
&& param_start.pdev_prop->c.source !=
AUDIO_SOURCE_I2S
&& param_start.pdev_prop->c.drv_type
== AUDIO_DRIVER_CAPT_HQ
/*FM recording is supported*/
&& telephonyIsEnabled == TRUE) {
aError("StartRecord failed. 48KHz in call");
record48K_in_call_is_blocked = 1;
kfree((void *)msgAudioCtrl);
return RESULT_ERROR;
}
}
/** EDN: not support 48KHz recording during voice call.*/
if (action_code == ACTION_AUD_StopRecord) {
BRCM_AUDIO_Param_Stop_t param_stop;
memcpy((void *)&param_stop, arg_param,
sizeof(BRCM_AUDIO_Param_Stop_t));
if (param_stop.callMode == MODEM_CALL
&& param_stop.pdev_prop->c.source !=
AUDIO_SOURCE_I2S
&& param_stop.pdev_prop->c.drv_type
== AUDIO_DRIVER_CAPT_HQ
/*FM recording is supported*/
&& telephonyIsEnabled == TRUE
&& record48K_in_call_is_blocked == 1
/* if start recording from digi mic in
* idle mode,then start voice call,
when stop recording the path shall
be disabled.
*/
) {
record48K_in_call_is_blocked = 0;
kfree((void *)msgAudioCtrl);
return RESULT_ERROR;
}
}
if (action_code == ACTION_AUD_DisableByPassVibra_CB)
action_code = ACTION_AUD_DisableByPassVibra;
params_size = AUDIO_Ctrl_Trigger_GetParamsSize(action_code);
msgAudioCtrl->action_code = action_code;
if (arg_param)
memcpy(&msgAudioCtrl->param, arg_param, params_size);
else
memset(&msgAudioCtrl->param, 0, params_size);
msgAudioCtrl->pCallBack = callback;
msgAudioCtrl->block = block;
INIT_WORK(&msgAudioCtrl->mwork , AudioCtrlWorkThread);
if (msgAudioCtrl->block == 1)
init_completion(&msgAudioCtrl->comp);
if (msgAudioCtrl && msgAudioCtrl->block == 1) {
QUEUE_WORK(pWorkqueue_AudioControl, msgAudioCtrl);
ret = wait_for_completion_timeout(
&msgAudioCtrl->comp,
msecs_to_jiffies(TIMEOUT_STOP_REQ_MS));
if (ret <= 0) {
aError(
"ERROR timeout waiting for"
"STOP REQ.t=%d ret=%ld action_code=%d\n",
TIMEOUT_STOP_REQ_MS, ret, action_code);
if (work_pending(&msgAudioCtrl->mwork)) {
aWarn("Freeing pending work, action code=%d",
action_code);
cancel_work_sync(&msgAudioCtrl->mwork);
kfree(msgAudioCtrl);
} else
msgAudioCtrl->timeout = TRUE;
return RESULT_ERROR;
} else {
if (arg_param != NULL)
memcpy(arg_param, &msgAudioCtrl->param,
params_size);
else
memset(&msgAudioCtrl->param, 0, params_size);
}
kfree(msgAudioCtrl);
} else
QUEUE_WORK(pWorkqueue_AudioControl, msgAudioCtrl);
return status;
}
#else
Result_t AUDIO_Ctrl_Trigger(BRCM_AUDIO_ACTION_en_t action_code,
void *arg_param, void *callback, int block)
{
TMsgAudioCtrl msgAudioCtrl;
Result_t status = RESULT_OK;
unsigned int len;
OSStatus_t osStatus;
int params_size;
unsigned long to_jiff = msecs_to_jiffies(BLOCK_WAITTIME_MS);
int fifo_avail;
unsigned long t_flag;
int is_atomic;
int is_cb = 0;
/** BEGIN: not support 48KHz recording during voice call */
static int record48K_in_call_is_blocked;
#if defined(CONFIG_BCM_MODEM)
if (is_dsp_timeout())
return RESULT_OK;
#endif
if (action_code == ACTION_AUD_StartRecord) {
BRCM_AUDIO_Param_Start_t param_start;
memcpy((void *)&param_start, arg_param,
sizeof(BRCM_AUDIO_Param_Start_t));
if (param_start.callMode == MODEM_CALL
&& param_start.rate == AUDIO_SAMPLING_RATE_48000
&& param_start.pdev_prop->c.source != AUDIO_SOURCE_I2S
&& param_start.pdev_prop->c.drv_type
== AUDIO_DRIVER_CAPT_HQ
/*FM recording is supported*/
&& telephonyIsEnabled == TRUE) {
aError("StartRecord failed. 48KHz in call");
record48K_in_call_is_blocked = 1;
return RESULT_ERROR;
}
}
if (action_code == ACTION_AUD_StopRecord) {
BRCM_AUDIO_Param_Stop_t param_stop;
memcpy((void *)&param_stop, arg_param,
sizeof(BRCM_AUDIO_Param_Stop_t));
if (param_stop.callMode == MODEM_CALL
&& param_stop.pdev_prop->c.source != AUDIO_SOURCE_I2S
&& param_stop.pdev_prop->c.drv_type
== AUDIO_DRIVER_CAPT_HQ
/*FM recording is supported*/
&& telephonyIsEnabled == TRUE
&& record48K_in_call_is_blocked == 1
/* if start recording from digi mic in idle mode,
then start voice call,
when stop recording the path shall be disabled.
*/
) {
record48K_in_call_is_blocked = 0;
return RESULT_ERROR;
}
}
/** EDN: not support 48KHz recording during voice call.*/
/*When multi blocking triggers (such as OpenPlay and ClosePlay) arrive
at the same time, each would compete for action_complete semaphore,
which may be intended for other trigger. As a result, incorrect
parameters are returned.
*/
if (block & 1)
mutex_lock(&mutexBlock);
if (action_code == ACTION_AUD_DisableByPassVibra_CB) {
action_code = ACTION_AUD_DisableByPassVibra;
is_cb = 1;
}
params_size = AUDIO_Ctrl_Trigger_GetParamsSize(action_code);
msgAudioCtrl.action_code = action_code;
if (arg_param)
memcpy(&msgAudioCtrl.param, arg_param, params_size);
else
memset(&msgAudioCtrl.param, 0, params_size);
msgAudioCtrl.pCallBack = callback;
msgAudioCtrl.block = block;
is_atomic = 0;
if (action_code == ACTION_AUD_StartPlay ||
action_code == ACTION_AUD_StopPlay ||
action_code == ACTION_AUD_PausePlay ||
action_code == ACTION_AUD_ResumePlay ||
action_code == ACTION_AUD_StartRecord ||
action_code == ACTION_AUD_StopRecord ||
action_code == ACTION_AUD_RateChange ||
action_code == ACTION_AUD_AddChannel ||
action_code == ACTION_AUD_RemoveChannel)
is_atomic = 1;
/* Triggers come to audio KFIFO from many threads: HAL, hwdep,
interrupt callback etc.
Audio KFIFO overflow may happen during stress test, due to that
either audio driver is stuck, or audio thread is blocked by other
threads.
- When KFIFO is half full, give warning.
- When KFIFO is full:
* For timer callback, ask to reshedule.
* For other non-atomic triggers, wait for completion.
* For atomic triggers, throw away. This is not ideal, but atomic
triggers require min delay and does not allow sleep or waiting.
*/
AUDIO_Ctrl_Trigger_Wait:
spin_lock_irqsave(&sgThreadData.m_lock, t_flag);
fifo_avail = kfifo_avail(&sgThreadData.m_pkfifo);
spin_unlock_irqrestore(&sgThreadData.m_lock, t_flag);
if (fifo_avail < sizeof(TMsgAudioCtrl)) {
aError("Audio KFIFO FULL avail %d, n_msg_in 0x%x, "
"n_msg_out 0x%x, last_action %d, action %d\n",
fifo_avail, n_msg_in, n_msg_out, last_action,
action_code);
if (is_atomic) {
aError("ERROR Audio KFIFO FULL throw atomic "
"action %d\n", action_code);
if (block & 1)
mutex_unlock(&mutexBlock);
return RESULT_ERROR;
} else if (is_cb) {
aError("Audio KFIFO FULL reschedule cb action %d\n",
action_code);
if (block & 1)
mutex_unlock(&mutexBlock);
return RESULT_ERROR;
} else {
unsigned long ret;
ret =
wait_for_completion_timeout
(&complete_kfifo,
msecs_to_jiffies(KFIFO_TIMEOUT_MS));
if (!ret) {
aError("ERROR Audio KFIFO timeout avail %d, "
"n_msg_in 0x%x, n_msg_out 0x%x, "
"last_action %d, action %d\n",
fifo_avail, n_msg_in, n_msg_out,
last_action, action_code);
if (block & 1)
mutex_unlock(&mutexBlock);
return RESULT_ERROR;
}
}
} else if (fifo_avail < KFIFO_SIZE / 2)
aWarn("Audio KFIFO HIGH avail %d, n_msg_in 0x%x, "
"n_msg_out 0x%x, last_action %d, action %d\n",
fifo_avail, n_msg_in, n_msg_out, last_action,
action_code);
spin_lock_irqsave(&sgThreadData.m_lock, t_flag);
fifo_avail = kfifo_avail(&sgThreadData.m_pkfifo);
if (fifo_avail < sizeof(TMsgAudioCtrl)) {
/*this means trigger from other thead has taken the spot */
spin_unlock_irqrestore(&sgThreadData.m_lock, t_flag);
/*aError("Audio KFIFO FULL loop action %d, "
"cb %d, atomic %d\n",
action_code, is_cb, is_atomic); */
/*return RESULT_ERROR; */
goto AUDIO_Ctrl_Trigger_Wait;
}
len = kfifo_in(&sgThreadData.m_pkfifo,
(unsigned char *)&msgAudioCtrl, sizeof(TMsgAudioCtrl));
spin_unlock_irqrestore(&sgThreadData.m_lock, t_flag);
/*aTrace(LOG_AUDIO_CNTLR, "AUDIO_Ctrl_Trigger action %d, avail %d, "
"n_msg_in 0x%x, n_msg_out 0x%x, last_action %d\n",
action_code, fifo_avail, n_msg_in, n_msg_out, last_action);*/
if (len != sizeof(TMsgAudioCtrl))
aError
("Error AUDIO_Ctrl_Trigger len=%d expected %d\n", len,
sizeof(TMsgAudioCtrl));
#ifdef CONFIG_SMP
queue_work(sgThreadData.pWorkqueue_AudioControl,
&sgThreadData.mwork);
#else
queue_work_on(0, sgThreadData.pWorkqueue_AudioControl,
&sgThreadData.mwork);
#endif
if (block & 1) {
osStatus =
OSSEMAPHORE_Obtain(sgThreadData.action_complete, to_jiff);
if (osStatus != OSSTATUS_SUCCESS) {
aWarn("AUDIO_Ctrl_Trigger Timeout=%d\r\n", osStatus);
status = RESULT_ERROR;
mutex_unlock(&mutexBlock);
return status;
}
while (1) {
/* wait for output from output fifo */
len =
kfifo_out_locked(&sgThreadData.m_pkfifo_out,
(unsigned char *)&msgAudioCtrl,
sizeof(TMsgAudioCtrl),
&sgThreadData.m_lock_out);
/*
* Commenting debug prints to eliminate compilation
* errors for kfifo member access
*/
/*
* if( (len != sizeof(TMsgAudioCtrl)) && (len!=0) )
* DEBUG("Error AUDIO_Ctrl_Trigger
* len=%d expected %d in=%d, out=%d\n", len,
* sizeof(TMsgAudioCtrl),
* sgThreadData.m_pkfifo_out.in,
* sgThreadData.m_pkfifo_out.out);
*/
if (len == 0) /* FIFO empty sleep */
break;
if (arg_param)
memcpy(arg_param, &msgAudioCtrl.param,
params_size);
}
mutex_unlock(&mutexBlock);
}
return status;
}
#endif
#ifdef CONFIG_ARCH_JAVA
static void AUDIO_Ctrl_Process(TMsgAudioCtrl *msgAudioCtrl)
{
BRCM_AUDIO_ACTION_en_t action_code = msgAudioCtrl->action_code;
void *arg_param = &msgAudioCtrl->param;
int block = msgAudioCtrl->block;
#else
static void AUDIO_Ctrl_Process(BRCM_AUDIO_ACTION_en_t action_code,
void *arg_param, void *callback, int block)
{
TMsgAudioCtrl msgAudioCtrl;
unsigned int len;
#endif
int i = 0;
unsigned int path = 0;
#ifdef CHECK_AADMAC_AUTOGATE_STATUS
if (get_chip_id() < KONA_CHIP_ID_JAVA_A0) {
if (AUDCTRL_AadmacAutoGateStatus())
/* this should never happen */
aError("\n %lx:AUDIO_Ctrl_Process-"
"!!! AADMAC_ENABLE_AUTO_GATE was set !!!\n",
jiffies);
}
#endif
switch (action_code) {
case ACTION_AUD_OpenPlay:
{
BRCM_AUDIO_Param_Open_t *param_open =
(BRCM_AUDIO_Param_Open_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_OpenPlay. stream=%d\n",
jiffies, param_open->stream);
param_open->drv_handle =
AUDIO_DRIVER_Open(param_open->pdev_prop->p[0].
drv_type);
if (param_open->drv_handle == NULL)
aError("\n %lx:AUDIO_Ctrl_Process-"
"AUDIO_DRIVER_Open failed. stream=%d\n",
jiffies, param_open->stream);
}
break;
case ACTION_AUD_ClosePlay:
{
BRCM_AUDIO_Param_Close_t *param_close =
(BRCM_AUDIO_Param_Close_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_ClosePlay. stream=%d\n",
jiffies, param_close->stream);
AUDIO_DRIVER_Close(param_close->drv_handle);
}
break;
case ACTION_AUD_StartPlay:
{
BRCM_AUDIO_Param_Start_t *param_start =
(BRCM_AUDIO_Param_Start_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StartPlay. stream=%d\n",
jiffies, param_start->stream);
CAPH_ASSERT(param_start->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_start->stream <
(CTL_STREAM_PANEL_LAST - 1));
if ((param_start->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_AUDIO) ||
(param_start->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_EPT)) {
/* Enable the playback the path */
AUDCTRL_EnablePlay(param_start->pdev_prop->p[0].
source,
param_start->pdev_prop->p[0].
sink, param_start->channels,
param_start->rate,
param_start->bitsPerSample, &path);
pathID[param_start->stream] = path;
AUDIO_DRIVER_Ctrl(param_start->drv_handle,
AUDIO_DRIVER_START,
&param_start->pdev_prop->p[0].
sink);
} else if (param_start->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_VOICE) {
AUDIO_DRIVER_Ctrl(param_start->drv_handle,
AUDIO_DRIVER_START, NULL);
}
}
break;
case ACTION_AUD_StopPlay:
{
BRCM_AUDIO_Param_Stop_t *param_stop =
(BRCM_AUDIO_Param_Stop_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StopPlay. stream=%d\n",
jiffies, param_stop->stream);
CAPH_ASSERT(param_stop->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_stop->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDIO_DRIVER_Ctrl(param_stop->drv_handle,
AUDIO_DRIVER_STOP, NULL);
/* Remove secondary playback path if it's in use */
for (i = (MAX_PLAYBACK_DEV - 1); i > 0; i--) {
if (param_stop->pdev_prop->p[i].sink !=
AUDIO_SINK_UNDEFINED) {
AUDCTRL_RemovePlaySpk(param_stop->
pdev_prop->p[0]
.source,
param_stop->
pdev_prop->p[i].
sink,
pathID
[param_stop->
stream]);
}
}
if ((param_stop->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_AUDIO)
|| (param_stop->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_EPT)) {
/* disable the playback path */
AUDCTRL_DisablePlay(param_stop->source,
param_stop->sink,
pathID[param_stop->stream]);
pathID[param_stop->stream] = 0;
}
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_StopPlay"
" completed. stream=%d\n", param_stop->stream);
}
break;
case ACTION_AUD_BufferReady:
{
BRCM_AUDIO_Param_BufferReady_t *param_bufferready =
(BRCM_AUDIO_Param_BufferReady_t *) arg_param;
/* don't trace here, too frequent
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_BufferReady. stream=%d\n",
jiffies, param_bufferready->stream);*/
CAPH_ASSERT(param_bufferready->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_bufferready->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDIO_DRIVER_Ctrl(param_bufferready->drv_handle,
AUDIO_DRIVER_BUFFER_READY, NULL);
/*aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_BufferReady"
" completed. stream=%d\n", param_bufferready->stream);*/
}
break;
case ACTION_AUD_PausePlay:
{
BRCM_AUDIO_Param_Pause_t *param_pause =
(BRCM_AUDIO_Param_Pause_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_PausePlay. stream=%d\n",
jiffies, param_pause->stream);
CAPH_ASSERT(param_pause->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_pause->stream <
(CTL_STREAM_PANEL_LAST - 1));
if ((param_pause->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_AUDIO)
|| (param_pause->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_EPT)) {
/* disable the playback path */
AUDCTRL_DisablePlay(param_pause->pdev_prop->p[0]
.source,
param_pause->pdev_prop->
p[0].sink,
pathID[param_pause->
stream]);
pathID[param_pause->stream] = 0;
}
AUDIO_DRIVER_Ctrl(param_pause->drv_handle,
AUDIO_DRIVER_PAUSE, NULL);
}
break;
case ACTION_AUD_ResumePlay:
{
BRCM_AUDIO_Param_Resume_t *param_resume =
(BRCM_AUDIO_Param_Resume_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_ResumePlay. stream=%d\n",
jiffies, param_resume->stream);
CAPH_ASSERT(param_resume->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_resume->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDIO_DRIVER_Ctrl(param_resume->drv_handle,
AUDIO_DRIVER_RESUME, NULL);
if ((param_resume->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_AUDIO)
|| (param_resume->pdev_prop->p[0].drv_type ==
AUDIO_DRIVER_PLAY_EPT)) {
/* Enable the playback the path */
AUDCTRL_EnablePlay(param_resume->pdev_prop->p[0]
.source,
param_resume->pdev_prop->
p[0].sink,
param_resume->channels,
param_resume->bits_per_sample,
param_resume->rate, &path);
pathID[param_resume->stream] = path;
}
}
break;
case ACTION_AUD_StartRecord:
{
BRCM_AUDIO_Param_Start_t *param_start =
(BRCM_AUDIO_Param_Start_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StartRecord. stream=%d\n",
jiffies, param_start->stream);
CAPH_ASSERT(param_start->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_start->stream <
(CTL_STREAM_PANEL_LAST - 1));
/* allow FM recording in call mode */
/*
* AUDCTRL_EnableRecord enables HW path, reads SYSPARM
* and sets HW gains as defined in SYSPARM.
*/
/* We prevent core idle untill rec is active */
if (voice_qos_state)
pi_mgr_qos_request_update(&voice_recorder_qos_node, 0);
AUDCTRL_EnableRecord(param_start->pdev_prop->c.
source,
param_start->pdev_prop->c.
sink,
param_start->channels,
param_start->rate, &path);
pathID[param_start->stream] = path;
if ((param_start->pdev_prop->c.drv_type ==
AUDIO_DRIVER_CAPT_HQ)
|| (param_start->pdev_prop->c.drv_type ==
AUDIO_DRIVER_CAPT_EPT)) {
AUDIO_DRIVER_Ctrl(param_start->drv_handle,
AUDIO_DRIVER_START,
&param_start->pdev_prop->c.
source);
} else {
voice_rec_t voiceRecStr;
memset(&voiceRecStr, 0, sizeof(voice_rec_t));
voiceRecStr.recordMode = param_start->mixMode;
voiceRecStr.callMode = param_start->callMode;
AUDIO_DRIVER_Ctrl(param_start->drv_handle,
AUDIO_DRIVER_START,
&voiceRecStr);
}
}
break;
case ACTION_AUD_StopRecord:
{
BRCM_AUDIO_Param_Stop_t *param_stop =
(BRCM_AUDIO_Param_Stop_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StopRecord. stream=%d\n",
jiffies, param_stop->stream);
CAPH_ASSERT(param_stop->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& param_stop->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDIO_DRIVER_Ctrl(param_stop->drv_handle,
AUDIO_DRIVER_STOP, NULL);
AUDCTRL_DisableRecord(param_stop->pdev_prop->c.source,
param_stop->pdev_prop->c.sink,
pathID[param_stop->stream]);
pathID[param_stop->stream] = 0;
/*Re-enable core idle*/
if (voice_qos_state)
pi_mgr_qos_request_update(&voice_recorder_qos_node,
PI_MGR_QOS_DEFAULT_VALUE);
}
break;
case ACTION_AUD_OpenRecord:
{
BRCM_AUDIO_Param_Open_t *param_open =
(BRCM_AUDIO_Param_Open_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_OpenRecord. stream=%d\n",
jiffies, param_open->stream);
param_open->drv_handle =
AUDIO_DRIVER_Open(param_open->pdev_prop->c.
drv_type);
if (param_open->drv_handle == NULL)
aError("param_open->drv_handle - 0x%lx\n",
(UInt32) param_open->drv_handle);
}
break;
case ACTION_AUD_CloseRecord:
{
BRCM_AUDIO_Param_Close_t *param_close =
(BRCM_AUDIO_Param_Close_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_CloseRecord. stream=%d\n",
jiffies, param_close->stream);
AUDIO_DRIVER_Close(param_close->drv_handle);
}
break;
case ACTION_AUD_AddChannel:
{
BRCM_AUDIO_Param_Spkr_t *parm_spkr =
(BRCM_AUDIO_Param_Spkr_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_AddChannel. stream=%d\n",
jiffies, parm_spkr->stream);
CAPH_ASSERT(parm_spkr->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_spkr->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_AddPlaySpk(parm_spkr->src, parm_spkr->sink,
pathID[parm_spkr->stream]);
}
break;
case ACTION_AUD_RemoveChannel:
{
BRCM_AUDIO_Param_Spkr_t *parm_spkr =
(BRCM_AUDIO_Param_Spkr_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_RemoveChannel. stream=%d\n",
jiffies, parm_spkr->stream);
CAPH_ASSERT(parm_spkr->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_spkr->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_RemovePlaySpk(parm_spkr->src, parm_spkr->sink,
pathID[parm_spkr->stream]);
}
break;
case ACTION_AUD_EnableTelephony:
{
BRCM_AUDIO_Param_Call_t *parm_call =
(BRCM_AUDIO_Param_Call_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_EnableTelephony:mic=%d, spkr=%d\n",
parm_call->new_mic, parm_call->new_spkr);
telephonyIsEnabled = TRUE; /*DSP is using mic path */
AUDCTRL_EnableTelephony(parm_call->new_mic,
parm_call->new_spkr);
}
break;
case ACTION_AUD_DisableTelephony:
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_DisableTelephony:\n");
AUDCTRL_DisableTelephony();
telephonyIsEnabled = FALSE;
break;
case ACTION_AUD_SetTelephonyMicSpkr:
{
BRCM_AUDIO_Param_Call_t *parm_call =
(BRCM_AUDIO_Param_Call_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetTelephonyMicSpkr:mic=%d, spkr=%d\n",
parm_call->new_mic, parm_call->new_spkr);
AUDCTRL_SetTelephonyMicSpkr(parm_call->new_mic,
parm_call->new_spkr,
false);
}
break;
case ACTION_AUD_MutePlayback:
{
BRCM_AUDIO_Param_Mute_t *parm_mute =
(BRCM_AUDIO_Param_Mute_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_MutePlayback. stream=%d\n",
jiffies, parm_mute->stream);
CAPH_ASSERT(parm_mute->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_mute->stream <
(CTL_STREAM_PANEL_LAST - 1));
/*
* currently driver doesnt handle Mute for left/right
* channels
*/
AUDCTRL_SetPlayMute(parm_mute->source,
parm_mute->sink,
parm_mute->mute1,
pathID[parm_mute->stream]);
}
break;
case ACTION_AUD_MuteRecord:
{
BRCM_AUDIO_Param_Mute_t *parm_mute =
(BRCM_AUDIO_Param_Mute_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_MuteRecord. stream=%d\n",
jiffies, parm_mute->stream);
CAPH_ASSERT(parm_mute->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_mute->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_SetRecordMute(parm_mute->source,
parm_mute->mute1,
pathID[parm_mute->stream]);
}
break;
case ACTION_AUD_EnableByPassVibra:
{
BRCM_AUDIO_Param_Vibra_t *parm_vibra =
(BRCM_AUDIO_Param_Vibra_t *) arg_param;
#ifdef USE_HR_TIMER
int isHRTimActive = 0;
#endif
aTrace(LOG_AUDIO_CNTLR,
"ACTION_AUD_EnableVibra"
"and SetVibraStrength\n");
#ifdef CONFIG_AUDIO_S2
PCM_Vibra_Gen_Start(parm_vibra->strength);
#else
AUDCTRL_EnableBypassVibra(parm_vibra->strength,
parm_vibra->direction);
#endif
#ifdef USE_HR_TIMER
isHRTimActive = hrtimer_active(&hr_timer);
if (isHRTimActive) {
aTrace(LOG_AUDIO_CNTLR,
"Hrtimer cancel is going to be called\n");
hrtimer_cancel(&hr_timer);
}
if (parm_vibra->duration != 0) {
ktime = ktime_set(parm_vibra->duration/1000,
(parm_vibra->duration%1000)*1000000);
hrtimer_start(&hr_timer, ktime,
HRTIMER_MODE_REL);
}
#else
if (gpVibratorTimer) {
del_timer_sync(gpVibratorTimer);
gpVibratorTimer = NULL;
}
if (parm_vibra->duration != 0) {
gpVibratorTimer = &gTimerVib;
init_timer(gpVibratorTimer);
gpVibratorTimer->function = TimerCbStopVibrator;
gpVibratorTimer->data = 0;
gpVibratorTimer->expires = jiffies +
msecs_to_jiffies(parm_vibra->duration);
add_timer(gpVibratorTimer);
}
#endif
}
break;
case ACTION_AUD_DisableByPassVibra:
{
#ifdef USE_HR_TIMER
int isHRTimActive = 0;
isHRTimActive = hrtimer_active(&hr_timer);
if (isHRTimActive) {
aTrace(LOG_AUDIO_CNTLR,
"Hrtimer cancel is going to be called"
"from Disable Vibra\n");
hrtimer_cancel(&hr_timer);
}
#else
if (gpVibratorTimer) {
del_timer_sync(gpVibratorTimer);
gpVibratorTimer = NULL;
}
#endif
/* stop it */
aTrace(LOG_AUDIO_CNTLR,
"ACTION_AUD_DisableByPassVibra\n");
#ifdef CONFIG_AUDIO_S2
PCM_Vibra_Gen_Stop();
#else
AUDCTRL_DisableBypassVibra();
#endif
}
break;
case ACTION_AUD_SetPlaybackVolume:
{
BRCM_AUDIO_Param_Volume_t *parm_vol =
(BRCM_AUDIO_Param_Volume_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SetPlaybackVolume. stream=%d\n",
jiffies, parm_vol->stream);
CAPH_ASSERT(parm_vol->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_vol->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_SetPlayVolume(parm_vol->source, parm_vol->sink,
parm_vol->gain_format,
parm_vol->volume1,
parm_vol->volume2,
pathID[parm_vol->stream]);
}
break;
case ACTION_AUD_SetRecordGain:
{
BRCM_AUDIO_Param_Volume_t *parm_vol =
(BRCM_AUDIO_Param_Volume_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SetRecordVolume. stream=%d\n",
jiffies, parm_vol->stream);
CAPH_ASSERT(parm_vol->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_vol->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_SetRecordGain(parm_vol->source,
AUDIO_GAIN_FORMAT_mB,
parm_vol->volume1,
parm_vol->volume2,
pathID[parm_vol->stream]);
}
break;
case ACTION_AUD_SetTelephonySpkrVolume:
{
BRCM_AUDIO_Param_Volume_t *parm_vol =
(BRCM_AUDIO_Param_Volume_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetTelephonySpkrVolume:sink=%d, vol=%d\n",
(int)parm_vol->sink, (int)parm_vol->volume1);
AUDCTRL_SetTelephonySpkrVolume(parm_vol->sink,
parm_vol->volume1,
parm_vol->gain_format);
}
break;
case ACTION_AUD_SwitchSpkr:
{
BRCM_AUDIO_Param_Spkr_t *parm_spkr =
(BRCM_AUDIO_Param_Spkr_t *) arg_param;
AudioMode_t audio_mode;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SwitchSpkr. stream=%d\n",
jiffies, parm_spkr->stream);
CAPH_ASSERT(parm_spkr->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_spkr->stream <
(CTL_STREAM_PANEL_LAST - 1));
audio_mode = GetAudioModeBySink(parm_spkr->sink);
AUDCTRL_SaveAudioMode(audio_mode);
AUDCTRL_SwitchPlaySpk(parm_spkr->src, parm_spkr->sink,
pathID[parm_spkr->stream]);
}
break;
case ACTION_AUD_SetAudioMode:
{
BRCM_AUDIO_Param_SetMode_t *parm_setmode =
(BRCM_AUDIO_Param_SetMode_t *) arg_param;
AudioMode_t tempMode =
(AudioMode_t) parm_setmode->aud_mode;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetAudioMode:new_mode=%d\n",
parm_setmode->aud_mode);
AUDCTRL_SetAudioModeBT(tempMode, AUDCTRL_GetAudioApp());
}
break;
case ACTION_AUD_CommitAudioProfile:
{
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_CommitAudioProfile:Mode=%d, app=%d\n",
AUDCTRL_GetAudioMode(), AUDCTRL_GetAudioApp());
AUDCTRL_SetAudioMode(AUDCTRL_GetAudioMode(),
AUDCTRL_GetAudioApp());
}
break;
case ACTION_AUD_SetHWLoopback:
{
BRCM_AUDIO_Param_Loopback_t *parm_loop =
(BRCM_AUDIO_Param_Loopback_t *) arg_param;
AUDCTRL_SetAudioLoopback(parm_loop->parm,
(AUDIO_SOURCE_Enum_t)
parm_loop->mic,
(AUDIO_SINK_Enum_t) parm_loop->
spkr, (int)parm_loop->mode);
}
break;
case ACTION_AUD_EnableFMPlay:
{
BRCM_AUDIO_Param_FM_t *parm_FM =
(BRCM_AUDIO_Param_FM_t *) arg_param;
CAPH_ASSERT(parm_FM->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_FM->stream <
(CTL_STREAM_PANEL_LAST - 1));
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_EnableFMPlay\n");
/*
* do not change voice call's audio mode. will delete
* the lines
*
* can set music app and mode
*/
/* re-enable FM; need to fill audio app */
AUDCTRL_SaveAudioMode((AudioMode_t) parm_FM->sink);
AUDCTRL_EnablePlay(parm_FM->source,
parm_FM->sink,
AUDIO_CHANNEL_STEREO,
AUDIO_SAMPLING_RATE_48000,
16, &path);
pathID[parm_FM->stream] = path;
}
break;
case ACTION_AUD_DisableFMPlay:
{
BRCM_AUDIO_Param_FM_t *parm_FM =
(BRCM_AUDIO_Param_FM_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_DisableFMPlay\n");
CAPH_ASSERT(parm_FM->stream >=
(CTL_STREAM_PANEL_FIRST - 1)
&& parm_FM->stream <
(CTL_STREAM_PANEL_LAST - 1));
AUDCTRL_DisablePlay(parm_FM->source, parm_FM->sink,
pathID[parm_FM->stream]);
pathID[parm_FM->stream] = 0;
}
break;
case ACTION_AUD_SetARM2SPInst:
{
BRCM_AUDIO_Param_FM_t *parm_FM =
(BRCM_AUDIO_Param_FM_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetARM2SPInst\n");
AUDCTRL_SetArm2spParam(CSL_CAPH_CFG_ARM2SP_FM,
parm_FM->fm_mix);
}
break;
case ACTION_AUD_SetPrePareParameters:
{
BRCM_AUDIO_Param_Prepare_t *parm_prepare =
(BRCM_AUDIO_Param_Prepare_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SetPrePareParameters. stream=%d\n",
jiffies, parm_prepare->stream);
/* set the callback */
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_CB,
(void *)&parm_prepare->cbParams);
/* set the count of periods */
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_PERIOD_COUNT,
(void *)&parm_prepare->period_count);
/* set the interrupt period */
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_INT_PERIOD,
(void *)&parm_prepare->period_bytes);
/* set the buffer params */
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_BUF_PARAMS,
(void *)&parm_prepare->buf_param);
/* Configure stream params */
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_CONFIG,
(void *)&parm_prepare->drv_config);
}
break;
case ACTION_AUD_MuteTelephony:
{
BRCM_AUDIO_Param_Mute_t *parm_mute =
(BRCM_AUDIO_Param_Mute_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_MuteTelephony: source=%d,mute1=%d\n",
(int)parm_mute->source, (int)parm_mute->mute1);
AUDCTRL_SetTelephonyMicMute(parm_mute->source,
parm_mute->mute1);
}
break;
case ACTION_AUD_DisableECNSTelephony:
aTrace(LOG_AUDIO_CNTLR, "Telephony : Turning Off EC and NS\n");
#ifdef CONFIG_AUDIO_FEATURE_SET_DISABLE_ECNS
/* when turning off EC and NS, using
* AUDIO_MODE_HANDSFREE as customer's request
*/
AUDCTRL_SetAudioMode(AUDIO_MODE_HANDSFREE,
AUDCTRL_GetAudioApp());
#endif
AUDCTRL_EC(FALSE, 0);
AUDCTRL_NS(FALSE);
break;
case ACTION_AUD_EnableECNSTelephony:
aTrace(LOG_AUDIO_CNTLR, "Telephony : Turning On EC and NS\n");
AUDCTRL_EC(TRUE, 0);
AUDCTRL_NS(TRUE);
break;
case ACTION_AUD_RateChange:
{
BRCM_AUDIO_Param_RateChange_t *param_rate_change =
(BRCM_AUDIO_Param_RateChange_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_RateChange: codecID=%d\n",
param_rate_change->codecID);
/* 0x0A as per 3GPP 26.103 Sec 6.3 indicates AMR WB
* AUDIO_ID_CALL16k
* 0x06 indicates AMR NB
*/
AUDCTRL_Telephony_RequestRateChange(param_rate_change->
codecID);
}
break;
case ACTION_AUD_HandleCPReset:
{
BRCM_AUDIO_Param_cpReset_t *param_cpReset =
(BRCM_AUDIO_Param_cpReset_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR, "ACTION_AUD_HandleCPReset\n");
AUDCTRL_HandleCPReset(param_cpReset->cp_reset_start);
}
break;
case ACTION_AUD_SetAudioApp:
{
BRCM_AUDIO_Param_SetApp_t *parm_setapp =
(BRCM_AUDIO_Param_SetApp_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetAudioApp: aud_app=%d\n",
parm_setapp->aud_app);
AUDCTRL_SaveAudioApp(parm_setapp->aud_app);
}
break;
case ACTION_AUD_RemoveAudioApp:
{
BRCM_AUDIO_Param_SetApp_t *parm_rmapp =
(BRCM_AUDIO_Param_SetApp_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_RemvoeAudioApp: aud_app=%d\n",
parm_rmapp->aud_app);
AUDCTRL_RemoveAudioApp(parm_rmapp->aud_app);
}
break;
case ACTION_AUD_AMPEnable:
{
BRCM_AUDIO_Param_AMPCTL_t *parm_setamp =
(BRCM_AUDIO_Param_AMPCTL_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_AMPEnable: amp_status=%d\n",
(int)parm_setamp->amp_status);
AUDCTRL_EnableAmp(parm_setamp->amp_status);
}
break;
case ACTION_AUD_SetCallMode:
{
BRCM_AUDIO_Param_CallMode_t *parm_callmode =
(BRCM_AUDIO_Param_CallMode_t *)arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_SetCallMode: callMode=%d\n",
(int)parm_callmode->callMode);
AUDCTRL_SetCallMode(parm_callmode->callMode);
}
break;
case ACTION_AUD_ConnectDL: /* PTT call */
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_ConnectDL:\n");
AUDCTRL_ConnectDL();
break;
case ACTION_AUD_UpdateUserVolSetting:
{
BRCM_AUDIO_Param_Volume_t *parm_vol =
(BRCM_AUDIO_Param_Volume_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"AUDIO_Ctrl_Process ACTION_AUD_UpdateUserVolSetting:\n");
AUDCTRL_UpdateUserVolSetting(
parm_vol->sink,
parm_vol->volume1,
parm_vol->volume2,
parm_vol->app);
}
break;
case ACTION_AUD_OpenVoIP:
{
BRCM_AUDIO_Param_Open_t *param_open =
(BRCM_AUDIO_Param_Open_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_OpenVoIP.\n", jiffies);
param_open->drv_handle =
AUDIO_DRIVER_Open(param_open->drv_type);
if (param_open->drv_handle == NULL)
aError("\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_OpenVoIP failed.\n",
jiffies);
}
break;
case ACTION_AUD_CloseVoIP:
{
BRCM_AUDIO_Param_Close_t *param_close =
(BRCM_AUDIO_Param_Close_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_CloseVoIP.\n", jiffies);
AUDIO_DRIVER_Close(param_close->drv_handle);
}
break;
case ACTION_AUD_SET_VOIP_UL_CB:
{
BRCM_AUDIO_Param_Prepare_t *parm_prepare =
(BRCM_AUDIO_Param_Prepare_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SET_VOIP_UL_CB.\n", jiffies);
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_VOIP_UL_CB,
(void *)&parm_prepare->cbParams);
}
break;
case ACTION_AUD_SET_VOIP_DL_CB:
{
BRCM_AUDIO_Param_Prepare_t *parm_prepare =
(BRCM_AUDIO_Param_Prepare_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_SET_VOIP_DL_CB.\n", jiffies);
AUDIO_DRIVER_Ctrl(parm_prepare->drv_handle,
AUDIO_DRIVER_SET_VOIP_DL_CB,
(void *)&parm_prepare->cbParams);
}
break;
case ACTION_AUD_StartVoIP:
{
BRCM_AUDIO_Param_Start_t *param_start =
(BRCM_AUDIO_Param_Start_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StartVoIPl.\n", jiffies);
AUDIO_DRIVER_Ctrl(param_start->drv_handle,
AUDIO_DRIVER_START, param_start->data);
}
break;
case ACTION_AUD_StopVoIP:
{
BRCM_AUDIO_Param_Stop_t *param_stop =
(BRCM_AUDIO_Param_Stop_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_StopVoIP.\n", jiffies);
AUDIO_DRIVER_Ctrl(param_stop->drv_handle,
AUDIO_DRIVER_STOP, NULL);
}
break;
case ACTION_AUD_BTTest:
{
BRCM_AUDIO_Param_BT_Test_t *param_bt =
(BRCM_AUDIO_Param_BT_Test_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_BTTest.\n", jiffies);
AUDCTRL_SetBTMode(param_bt->mode);
}
break;
case ACTION_AUD_CfgIHF:
{
BRCM_AUDIO_Param_Cfg_IHF_t *param_ihf =
(BRCM_AUDIO_Param_Cfg_IHF_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_CfgIHF.\n", jiffies);
AUDCTRL_SetIHFmode(param_ihf->stIHF);
}
break;
case ACTION_AUD_CfgSSP:
{
BRCM_AUDIO_Param_Cfg_SSP_t *param_ssp =
(BRCM_AUDIO_Param_Cfg_SSP_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_CfgSSP.\n", jiffies);
AUDCTRL_ConfigSSP(param_ssp->mode,
param_ssp->bus,
param_ssp->en_lpbk);
}
break;
case ACTION_AUD_HwCtl:
{
BRCM_AUDIO_Param_HwCtl_t *param_hwCtl =
(BRCM_AUDIO_Param_HwCtl_t *) arg_param;
aTrace(LOG_AUDIO_CNTLR,
"\n %lx:AUDIO_Ctrl_Process-"
"ACTION_AUD_HwCtl.\n", jiffies);
AUDCTRL_HardwareControl(param_hwCtl->access_type,
param_hwCtl->arg1,
param_hwCtl->arg2,
param_hwCtl->arg3,
param_hwCtl->arg4);
}
break;
case ACTION_AUD_AtCtl:
{
BRCM_AUDIO_Param_AtCtl_t parm_atctl;
memcpy((void *)&parm_atctl, arg_param,
sizeof(BRCM_AUDIO_Param_AtCtl_t));
if (parm_atctl.isGet)
AtAudCtlHandler_get(parm_atctl.cmdIndex,
parm_atctl.pChip,
parm_atctl.ParamCount,
parm_atctl.Params);
else
AtAudCtlHandler_put(parm_atctl.cmdIndex,
parm_atctl.pChip,
parm_atctl.ParamCount,
parm_atctl.Params);
/*copy values back to arg_param */
memcpy((void *)arg_param, (void *)&parm_atctl,
sizeof(BRCM_AUDIO_Param_AtCtl_t));
}
break;
default:
aError("Error AUDIO_Ctrl_Process Invalid action %d\n",
action_code);
break;
}
#ifdef CONFIG_ARCH_JAVA
if ((msgAudioCtrl->pCallBack != NULL) && (!msgAudioCtrl->timeout)) {
PFuncAudioCtrlCB pCB = (PFuncAudioCtrlCB)msgAudioCtrl->
pCallBack;
pCB(block);
}
#else
if (block & 1) {
/* put the message in output fifo if waiting */
msgAudioCtrl.action_code = action_code;
if (arg_param)
memcpy(&msgAudioCtrl.param, arg_param,
sizeof(BRCM_AUDIO_Control_Params_un_t));
else
memset(&msgAudioCtrl.param, 0,
sizeof(BRCM_AUDIO_Control_Params_un_t));
msgAudioCtrl.pCallBack = callback;
msgAudioCtrl.block = block;
len = kfifo_in_locked(&sgThreadData.m_pkfifo_out,
(unsigned char *)&msgAudioCtrl,
sizeof(TMsgAudioCtrl),
&sgThreadData.m_lock_out);
if (len != sizeof(TMsgAudioCtrl))
aError("Error AUDIO_Ctrl_Process "
"len=%d expected %d\n", len,
sizeof(TMsgAudioCtrl));
/* release the semaphore */
OSSEMAPHORE_Release(sgThreadData.action_complete);
}
if (callback) {
PFuncAudioCtrlCB pCB = (PFuncAudioCtrlCB)callback;
pCB(block);
}
#endif
}
#ifdef CONFIG_AUDIO_S2
/*store 2 periods*/
static const UInt16 sample_tone190_48m[VIBRA_PERIOD_BYTES] = {
0xFFFF, 0x032B, 0x065A, 0x098A, 0x0CB3, 0x0FDD, 0x1308, 0x1627,
0x194B, 0x1C69, 0x1F7E, 0x2293, 0x25A3, 0x28A6, 0x2BAB, 0x2EA7,
0x3196, 0x3483, 0x3767, 0x3A3E, 0x3D11, 0x3FDA, 0x4294, 0x4549,
0x47ED, 0x4A8B, 0x4D1D, 0x4F9E, 0x5217, 0x5484, 0x56DD, 0x592F,
0x5B72, 0x5DA1, 0x5FC7, 0x61DE, 0x63E0, 0x65D8, 0x67BE, 0x6994,
0x6B56, 0x6D0B, 0x6EAE, 0x703D, 0x71BC, 0x732A, 0x7482, 0x75CB,
0x7701, 0x7824, 0x7933, 0x7A30, 0x7B18, 0x7BEF, 0x7CB1, 0x7D5E,
0x7DF9, 0x7E80, 0x7EF2, 0x7F50, 0x7F9B, 0x7FD0, 0x7FF2, 0x7FFF,
0x7FF8, 0x7FDD, 0x7FAD, 0x7F6A, 0x7F12, 0x7EA6, 0x7E26, 0x7D92,
0x7CEA, 0x7C30, 0x7B5F, 0x7A7B, 0x7987, 0x787D, 0x7760, 0x7632,
0x74EF, 0x739C, 0x7235, 0x70BA, 0x6F32, 0x6D94, 0x6BE5, 0x6A29,
0x6858, 0x6676, 0x6488, 0x6287, 0x6075, 0x5E59, 0x5C2A, 0x59EB,
0x57A3, 0x5548, 0x52E1, 0x5071, 0x4DEF, 0x4B60, 0x48CC, 0x4626,
0x4374, 0x40BF, 0x3DF8, 0x3B28, 0x3855, 0x3572, 0x3288, 0x2F9C,
0x2CA2, 0x29A1, 0x269F, 0x2390, 0x207D, 0x1D6A, 0x1A4D, 0x172B,
0x140C, 0x10E5, 0x0DB9, 0x0A92, 0x0762, 0x0432, 0x0107, 0xFDD6,
0xFAA6, 0xF77D, 0xF44E, 0xF122, 0xEDFD, 0xEAD6, 0xE7B3, 0xE497,
0xE17C, 0xDE65, 0xDB59, 0xD84D, 0xD548, 0xD24F, 0xCF58, 0xCC68,
0xC986, 0xC6A7, 0xC3D2, 0xC10B, 0xBE49, 0xBB91, 0xB8E9, 0xB647,
0xB3B0, 0xB12C, 0xAEAF, 0xAC3F, 0xA9DC, 0xA78A, 0xA543, 0xA30A,
0xA0E4, 0x9EC9, 0x9CBD, 0x9AC5, 0x98D9, 0x96FE, 0x9537, 0x937D,
0x91D4, 0x9040, 0x8EBB, 0x8D47, 0x8BE8, 0x8A9A, 0x895E, 0x8836,
0x8720, 0x861D, 0x852F, 0x8453, 0x838A, 0x82D7, 0x8237, 0x81A8,
0x8131, 0x80CC, 0x807B, 0x803F, 0x8017, 0x8003, 0x8003, 0x8019,
0x8042, 0x807F, 0x80D0, 0x8137, 0x81AF, 0x823D, 0x82DF, 0x8393,
0x845D, 0x853A, 0x8628, 0x872C, 0x8845, 0x896C, 0x8AAA, 0x8BF9,
0x8D58, 0x8ECC, 0x9052, 0x91E8, 0x9391, 0x954C, 0x9714, 0x98F1,
0x9ADD, 0x9CD6, 0x9EE2, 0xA0FE, 0xA325, 0xA55F, 0xA7A6, 0xA9F8,
0xAC5C, 0xAECC, 0xB145, 0xB3D0, 0xB666, 0xB903, 0xBBB1, 0xBE6A,
0xC126, 0xC3F4, 0xC6C9, 0xC9A3, 0xCC8B, 0xCF7B, 0xD26E, 0xD56C,
0xD872, 0xDB79, 0xDE8A, 0xE1A1, 0xE4B7, 0xE7D7, 0xEAFC, 0xEE1D,
0xF148, 0xF475, 0xF79D, 0xFACC, 0xFDFD, 0x0128, 0x0459, 0x0789,
0x0AB1, 0x0DDF, 0x110A, 0x142C, 0x1752, 0x1A73, 0x1D8A, 0x20A2,
0x23B6, 0x26BE, 0x29C5, 0x2CC5, 0x2FB9, 0x32AC, 0x3596, 0x3872,
0x3B4B, 0x3E1B, 0x40DA, 0x4395, 0x4646, 0x48E5, 0x4B80, 0x4E0D,
0x508A, 0x52FE, 0x5566, 0x57BA, 0x5A07, 0x5C44, 0x5E6F, 0x608E,
0x62A0, 0x649B, 0x668E, 0x686E, 0x6A3B, 0x6BFA, 0x6DA8, 0x6F41,
0x70CC, 0x7246, 0x73A9, 0x74FF, 0x7640, 0x776D, 0x788A, 0x7992,
0x7A87, 0x7B69, 0x7C38, 0x7CF2, 0x7D9A, 0x7E2D, 0x7EAB, 0x7F16,
0x7F6D, 0x7FAF, 0x7FDE, 0x7FF9, 0x7FFE, 0x7FF0, 0x7FCE, 0x7F97,
0x7F4C, 0x7EEE, 0x7E7A, 0x7DF2, 0x7D57, 0x7CA8, 0x7BE5, 0x7B10,
0x7A25, 0x7926, 0x7818, 0x76F3, 0x75BC, 0x7475, 0x7319, 0x71AB,
0x702D, 0x6E9A, 0x6CF7, 0x6B45, 0x697F, 0x67A8, 0x65C4, 0x63CC,
0x61C5, 0x5FB2, 0x5D8C, 0x5B57, 0x5917, 0x56C6, 0x5467, 0x51FF,
0x4F84, 0x4CFE, 0x4A71, 0x47D2, 0x4529, 0x4278, 0x3FB9, 0x3CF0,
0x3A22, 0x3745, 0x3460, 0x3178, 0x2E83, 0x2B86, 0x2888, 0x257E,
0x226E, 0x1F5E, 0x1C43, 0x1925, 0x1608, 0x12E2, 0x0FB7, 0x0C93,
0x0964, 0x0634, 0x030A, 0xFFDA, 0xFCA8, 0xF97E, 0xF64F, 0xF322,
0xEFFC, 0xECD3, 0xE9AC, 0xE690, 0xE371, 0xE058, 0xDD48, 0xDA38,
0xD72F, 0xD432, 0xD136, 0xCE41, 0xCB59, 0xC876, 0xC59A, 0xC2CC,
0xC005, 0xBD46, 0xBA97, 0xB7EE, 0xB551, 0xB2C5, 0xB03F, 0xADC6,
0xAB61, 0xA901, 0xA6B1, 0xA473, 0xA241, 0xA01B, 0x9E09, 0x9C03,
0x9A0E, 0x982B, 0x9656, 0x9492, 0x92E1, 0x913F, 0x8FAE, 0x8E32,
0x8CC4, 0x8B6B, 0x8A25, 0x88F0, 0x87CD, 0x86C0, 0x85C4, 0x84DB,
0x8408, 0x8347, 0x8299, 0x8200, 0x817A, 0x810A, 0x80AD, 0x8063,
0x802E, 0x800E, 0x8001, 0x8009, 0x8026, 0x8055, 0x809A, 0x80F3,
0x8160, 0x81E2, 0x8275, 0x831E, 0x83DB, 0x84AB, 0x858F, 0x8687,
0x8790, 0x88AE, 0x89DF, 0x8B21, 0x8C77, 0x8DDF, 0x8F58, 0x90E4,
0x9283, 0x942F, 0x95F0, 0x97C2, 0x99A1, 0x9B93, 0x9D96, 0x9FA4,
0xA1C6, 0xA3F5, 0xA630, 0xA87E, 0xAAD9, 0xAD3D, 0xAFB2, 0xB235
};
static const UInt16 sample_tone195_48m[VIBRA_PERIOD_BYTES] = {
0xFFFF, 0x0344, 0x0687, 0x09CC, 0x0D0C, 0x104A, 0x1387, 0x16C0,
0x19F4, 0x1D25, 0x2051, 0x2378, 0x2699, 0x29B3, 0x2CC6, 0x2FD1,
0x32D5, 0x35D1, 0x38C3, 0x3BAB, 0x3E8B, 0x415F, 0x4429, 0x46E7,
0x4999, 0x4C3F, 0x4ED8, 0x5164, 0x53E3, 0x5654, 0x58B6, 0x5B0A,
0x5D4D, 0x5F83, 0x61A8, 0x63BB, 0x65C1, 0x67B3, 0x6994, 0x6B64,
0x6D22, 0x6ECF, 0x7067, 0x71EE, 0x7362, 0x74C2, 0x760F, 0x7748,
0x786E, 0x797F, 0x7A7C, 0x7B65, 0x7C38, 0x7CF8, 0x7DA2, 0x7E37,
0x7EB8, 0x7F23, 0x7F79, 0x7FBA, 0x7FE5, 0x7FFC, 0x7FFD, 0x7FE8,
0x7FBE, 0x7F7F, 0x7F2B, 0x7EC1, 0x7E42, 0x7DAE, 0x7D06, 0x7C48,
0x7B76, 0x7A8F, 0x7993, 0x7883, 0x7760, 0x7628, 0x74DD, 0x737E,
0x720C, 0x7086, 0x6EEE, 0x6D44, 0x6B88, 0x69B9, 0x67D9, 0x65E6,
0x63E5, 0x61D1, 0x5FAD, 0x5D7A, 0x5B37, 0x58E5, 0x5683, 0x5414,
0x5196, 0x4F0C, 0x4C73, 0x49CE, 0x471C, 0x4460, 0x4197, 0x3EC3,
0x3BE4, 0x38FD, 0x360C, 0x3311, 0x300E, 0x2D02, 0x29F0, 0x26D6,
0x23B6, 0x2090, 0x1D64, 0x1A34, 0x16FF, 0x13C6, 0x108B, 0x0D4C,
0x0A0B, 0x06C8, 0x0385, 0x0040, 0xFCFC, 0xF9B8, 0xF675, 0xF334,
0xEFF5, 0xECB9, 0xE980, 0xE64B, 0xE31A, 0xDFED, 0xDCC6, 0xD9A4,
0xD68A, 0xD376, 0xD06A, 0xCD66, 0xCA6A, 0xC776, 0xC48D, 0xC1AE,
0xBED8, 0xBC0D, 0xB94F, 0xB69C, 0xB3F4, 0xB159, 0xAECE, 0xAC4D,
0xA9DB, 0xA778, 0xA523, 0xA2DE, 0xA0A8, 0x9E82, 0x9C6C, 0x9A67,
0x9873, 0x9690, 0x94BE, 0x92FF, 0x9152, 0x8FB7, 0x8E2F, 0x8CBB,
0x8B57, 0x8A0A, 0x88CF, 0x87A8, 0x8695, 0x8596, 0x84AD, 0x83D7,
0x8317, 0x826A, 0x81D3, 0x8152, 0x80E4, 0x808C, 0x804A, 0x801D,
0x8004, 0x8002, 0x8015, 0x803E, 0x807C, 0x80CE, 0x8136, 0x81B3,
0x8246, 0x82EC, 0x83A9, 0x847A, 0x855E, 0x8658, 0x8766, 0x8889,
0x89BF, 0x8B0A, 0x8C67, 0x8DD8, 0x8F5B, 0x90F1, 0x929A, 0x9456,
0x9624, 0x9802, 0x99F2, 0x9BF4, 0x9E05, 0xA027, 0xA25A, 0xA49C,
0xA6ED, 0xA94D, 0xABBB, 0xAE38, 0xB0C3, 0xB35A, 0xB5FE, 0xB8AF,
0xBB6A, 0xBE32, 0xC105, 0xC3E2, 0xC6CA, 0xC9BA, 0xCCB4, 0xCFB7,
0xD2C2, 0xD5D4, 0xD8ED, 0xDC0D, 0xDF32, 0xE25E, 0xE58D, 0xE8C2,
0xEBFA, 0xEF36, 0xF274, 0xF5B5, 0xF8F8, 0xFC3B, 0xFF7F, 0x02C3,
0x0607, 0x094B, 0x0C8C, 0x0FCA, 0x1308, 0x1641, 0x1977, 0x1CA9,
0x1FD5, 0x22FD, 0x261D, 0x2938, 0x2C4D, 0x2F5A, 0x325F, 0x355C,
0x3850, 0x3B3A, 0x3E1A, 0x40F1, 0x43BB, 0x467C, 0x4930, 0x4BD8,
0x4E73, 0x5101, 0x5382, 0x55F5, 0x585A, 0x5AAF, 0x5CF6, 0x5F2D,
0x6154, 0x636B, 0x6572, 0x6767, 0x694C, 0x6B1E, 0x6CDF, 0x6E8D,
0x702A, 0x71B4, 0x732A, 0x748D, 0x75DD, 0x7719, 0x7841, 0x7957,
0x7A56, 0x7B42, 0x7C19, 0x7CDC, 0x7D8A, 0x7E22, 0x7EA6, 0x7F14,
0x7F6E, 0x7FB2, 0x7FE0, 0x7FFA, 0x7FFD, 0x7FED, 0x7FC7, 0x7F8A,
0x7F39, 0x7ED3, 0x7E57, 0x7DC7, 0x7D20, 0x7C67, 0x7B97, 0x7AB3,
0x79BB, 0x78AE, 0x778E, 0x7659, 0x7511, 0x73B4, 0x7245, 0x70C3,
0x6F2E, 0x6D87, 0x6BCD, 0x6A02, 0x6823, 0x6634, 0x6435, 0x6224,
0x6003, 0x5DD2, 0x5B90, 0x5941, 0x56E2, 0x5476, 0x51F9, 0x4F70,
0x4CDA, 0x4A37, 0x4787, 0x44CC, 0x4205, 0x3F33, 0x3C56, 0x3970,
0x3680, 0x3386, 0x3084, 0x2D7B, 0x2A69, 0x2750, 0x2431, 0x210C,
0x1DE1, 0x1AB2, 0x177E, 0x1445, 0x110A, 0x0DCB, 0x0A8B, 0x0749,
0x0405, 0x00C1, 0xFD7D, 0xFA38, 0xF6F5, 0xF3B4, 0xF074, 0xED37,
0xE9FF, 0xE6C9, 0xE396, 0xE06A, 0xDD42, 0xDA21, 0xD704, 0xD3EF,
0xD0E1, 0xCDDD, 0xCADF, 0xC7EA, 0xC4FE, 0xC21E, 0xBF47, 0xBC7B,
0xB9BA, 0xB705, 0xB45C, 0xB1C0, 0xAF31, 0xACAF, 0xAA3B, 0xA7D6,
0xA57F, 0xA337, 0xA0FE, 0x9ED6, 0x9CBE, 0x9AB5, 0x98BF, 0x96D9,
0x9505, 0x9343, 0x9193, 0x8FF5, 0x8E6A, 0x8CF3, 0x8B8D, 0x8A3C,
0x88FF, 0x87D3, 0x86BD, 0x85BC, 0x84D0, 0x83F6, 0x8333, 0x8283,
0x81E9, 0x8164, 0x80F3, 0x8098, 0x8053, 0x8022, 0x8007, 0x8001,
0x8011, 0x8036, 0x8071, 0x80C0, 0x8125, 0x819F, 0x822E, 0x82D2,
0x838A, 0x8458, 0x853A, 0x8630, 0x873D, 0x885B, 0x898F, 0x8AD5,
0x8C30, 0x8D9E, 0x8F1D, 0x90B1, 0x9258, 0x9410, 0x95DB, 0x97B7,
0x99A4, 0x9BA3, 0x9DB3, 0x9FD3, 0xA203, 0xA441, 0xA691, 0xA8EF,
0xAB5B, 0xADD6, 0xB05E, 0xB2F3, 0xB594, 0xB844, 0xBAFE, 0xBDC4,
0xC095, 0xC372, 0xC656, 0xC947, 0xCC3F, 0xCF40, 0xD249, 0xD55B
};
static const UInt16 sample_tone200_48m[VIBRA_PERIOD_BYTES] = {
0x0000, 0x035A, 0x06B3, 0x0A0B, 0x0D62, 0x10B6, 0x1406, 0x1753,
0x1A9C, 0x1DE1, 0x2121, 0x245B, 0x278D, 0x2ABA, 0x2DDE, 0x30FC,
0x3410, 0x371B, 0x3A1C, 0x3D12, 0x3FFF, 0x42E1, 0x45B6, 0x487F,
0x4B3D, 0x4DEC, 0x508D, 0x5320, 0x55A5, 0x581B, 0x5A82, 0x5CD8,
0x5F1F, 0x6154, 0x6379, 0x658C, 0x678D, 0x697D, 0x6B58, 0x6D23,
0x6ED9, 0x707D, 0x720C, 0x7387, 0x74EE, 0x7641, 0x777F, 0x78A8,
0x79BC, 0x7ABA, 0x7BA2, 0x7C76, 0x7D33, 0x7DDA, 0x7E6C, 0x7EE7,
0x7F4B, 0x7F99, 0x7FD2, 0x7FF4, 0x7FFF, 0x7FF4, 0x7FD3, 0x7F99,
0x7F4C, 0x7EE6, 0x7E6C, 0x7DDB, 0x7D33, 0x7C76, 0x7BA3, 0x7ABB,
0x79BB, 0x78A7, 0x777F, 0x7641, 0x74EE, 0x7387, 0x720B, 0x707C,
0x6ED9, 0x6D23, 0x6B58, 0x697C, 0x678D, 0x658C, 0x6379, 0x6154,
0x5F1F, 0x5CD8, 0x5A82, 0x581B, 0x55A5, 0x5320, 0x508E, 0x4DEA,
0x4B3D, 0x487F, 0x45B7, 0x42E1, 0x4000, 0x3D14, 0x3A1C, 0x371B,
0x3410, 0x30FB, 0x2DDF, 0x2ABA, 0x278E, 0x245B, 0x2121, 0x1DE1,
0x1A9D, 0x1753, 0x1406, 0x10B5, 0x0D61, 0x0A0B, 0x06B3, 0x0359,
0x0000, 0xFCA5, 0xF94D, 0xF5F5, 0xF29F, 0xFE4B, 0xEBFA, 0xE8AC,
0xE564, 0xE21E, 0xDEDF, 0xDBA5, 0xD872, 0xD546, 0xD222, 0xCF05,
0xCBF1, 0xC8E5, 0xC5E4, 0xC2ED, 0xC001, 0xBD20, 0xBA4A, 0xB781,
0xB4C4, 0xB214, 0xAF73, 0xACE0, 0xAA5B, 0xA7E5, 0xA57F, 0xA328,
0xA0E1, 0x9EAC, 0x9C86, 0x9A74, 0x9873, 0x9685, 0x94A7, 0x92DD,
0x9127, 0x8F84, 0x8DF5, 0x8C79, 0x8B12, 0x89BF, 0x8882, 0x8759,
0x8645, 0x8546, 0x845D, 0x838A, 0x82CD, 0x8225, 0x8195, 0x8118,
0x80B5, 0x8066, 0x802E, 0x800C, 0x8001, 0x800D, 0x802E, 0x8066,
0x80B4, 0x8119, 0x8194, 0x8226, 0x82CD, 0x838A, 0x845D, 0x8546,
0x8645, 0x8759, 0x8881, 0x89BF, 0x8B12, 0x8C78, 0x8DF4, 0x8F84,
0x9127, 0x92DE, 0x94A8, 0x9684, 0x9873, 0x9A74, 0x9C87, 0x9EAC,
0xA0E1, 0xA328, 0xA57E, 0xA7E5, 0xAA5A, 0xACE0, 0xAF73, 0xB215,
0xB4C5, 0xB781, 0xBA49, 0xBD1F, 0xC000, 0xC2ED, 0xC5E4, 0xC8E6,
0xCBF0, 0xCF04, 0xD221, 0xD547, 0xD873, 0xDBA6, 0xDEDF, 0xE21F,
0xE563, 0xE8AD, 0xEBFA, 0xEf4B, 0xF29F, 0xF5F6, 0xF94D, 0xFCA7,
0x0000, 0x035A, 0x06B3, 0x0A0B, 0x0D62, 0x10B6, 0x1406, 0x1753,
0x1A9C, 0x1DE1, 0x2121, 0x245B, 0x278D, 0x2ABA, 0x2DDE, 0x30FC,
0x3410, 0x371B, 0x3A1C, 0x3D12, 0x3FFF, 0x42E1, 0x45B6, 0x487F,
0x4B3D, 0x4DEC, 0x508D, 0x5320, 0x55A5, 0x581B, 0x5A82, 0x5CD8,
0x5F1F, 0x6154, 0x6379, 0x658C, 0x678D, 0x697D, 0x6B58, 0x6D23,
0x6ED9, 0x707D, 0x720C, 0x7387, 0x74EE, 0x7641, 0x777F, 0x78A8,
0x79BC, 0x7ABA, 0x7BA2, 0x7C76, 0x7D33, 0x7DDA, 0x7E6C, 0x7EE7,
0x7F4B, 0x7F99, 0x7FD2, 0x7FF4, 0x7FFF, 0x7FF4, 0x7FD3, 0x7F99,
0x7F4C, 0x7EE6, 0x7E6C, 0x7DDB, 0x7D33, 0x7C76, 0x7BA3, 0x7ABB,
0x79BB, 0x78A7, 0x777F, 0x7641, 0x74EE, 0x7387, 0x720B, 0x707C,
0x6ED9, 0x6D23, 0x6B58, 0x697C, 0x678D, 0x658C, 0x6379, 0x6154,
0x5F1F, 0x5CD8, 0x5A82, 0x581B, 0x55A5, 0x5320, 0x508E, 0x4DEA,
0x4B3D, 0x487F, 0x45B7, 0x42E1, 0x4000, 0x3D14, 0x3A1C, 0x371B,
0x3410, 0x30FB, 0x2DDF, 0x2ABA, 0x278E, 0x245B, 0x2121, 0x1DE1,
0x1A9D, 0x1753, 0x1406, 0x10B5, 0x0D61, 0x0A0B, 0x06B3, 0x0359,
0x0000, 0xFCA5, 0xF94D, 0xF5F5, 0xF29F, 0xFE4B, 0xEBFA, 0xE8AC,
0xE564, 0xE21E, 0xDEDF, 0xDBA5, 0xD872, 0xD546, 0xD222, 0xCF05,
0xCBF1, 0xC8E5, 0xC5E4, 0xC2ED, 0xC001, 0xBD20, 0xBA4A, 0xB781,
0xB4C4, 0xB214, 0xAF73, 0xACE0, 0xAA5B, 0xA7E5, 0xA57F, 0xA328,
0xA0E1, 0x9EAC, 0x9C86, 0x9A74, 0x9873, 0x9685, 0x94A7, 0x92DD,
0x9127, 0x8F84, 0x8DF5, 0x8C79, 0x8B12, 0x89BF, 0x8882, 0x8759,
0x8645, 0x8546, 0x845D, 0x838A, 0x82CD, 0x8225, 0x8195, 0x8118,
0x80B5, 0x8066, 0x802E, 0x800C, 0x8001, 0x800D, 0x802E, 0x8066,
0x80B4, 0x8119, 0x8194, 0x8226, 0x82CD, 0x838A, 0x845D, 0x8546,
0x8645, 0x8759, 0x8881, 0x89BF, 0x8B12, 0x8C78, 0x8DF4, 0x8F84,
0x9127, 0x92DE, 0x94A8, 0x9684, 0x9873, 0x9A74, 0x9C87, 0x9EAC,
0xA0E1, 0xA328, 0xA57E, 0xA7E5, 0xAA5A, 0xACE0, 0xAF73, 0xB215,
0xB4C5, 0xB781, 0xBA49, 0xBD1F, 0xC000, 0xC2ED, 0xC5E4, 0xC8E6,
0xCBF0, 0xCF04, 0xD221, 0xD547, 0xD873, 0xDBA6, 0xDEDF, 0xE21F,
0xE563, 0xE8AD, 0xEBFA, 0xEf4B, 0xF29F, 0xF5F6, 0xF94D, 0xFCA7
};
static const UInt16 sample_tone205_48m[VIBRA_PERIOD_BYTES] = {
0x0001, 0x036B, 0x06DD, 0x0A4B, 0x0DB2, 0x111D, 0x147E, 0x17E3,
0x1B42, 0x1E9D, 0x21EC, 0x253A, 0x2882, 0x2BBC, 0x2EF4, 0x3224,
0x3544, 0x3861, 0x3B73, 0x3E74, 0x4170, 0x4459, 0x473D, 0x4A12,
0x4CD5, 0x4F8F, 0x523A, 0x54D1, 0x575D, 0x59D9, 0x5C3F, 0x5E9B,
0x60E3, 0x6316, 0x653B, 0x674D, 0x694B, 0x6B34, 0x6D0B, 0x6ECE,
0x707B, 0x7214, 0x7399, 0x7507, 0x7661, 0x77A5, 0x78D1, 0x79E9,
0x7AEA, 0x7BD3, 0x7CA7, 0x7D62, 0x7E07, 0x7E96, 0x7F0C, 0x7F6B,
0x7FB3, 0x7FE3, 0x7FFB, 0x7FFD, 0x7FE5, 0x7FB8, 0x7F73, 0x7F14,
0x7E9F, 0x7E13, 0x7D70, 0x7CB7, 0x7BE5, 0x7AFC, 0x79FF, 0x78E8,
0x77BB, 0x767C, 0x7523, 0x73B8, 0x7235, 0x709C, 0x6EF2, 0x6D30,
0x6B5B, 0x6974, 0x6776, 0x6566, 0x6347, 0x6111, 0x5ECA, 0x5C75,
0x5A0B, 0x5791, 0x550A, 0x5270, 0x4FC7, 0x4D13, 0x4A4C, 0x4777,
0x449B, 0x41AC, 0x3EB2, 0x3BB1, 0x38A1, 0x3584, 0x3265, 0x2F36,
0x2BFE, 0x28C5, 0x257E, 0x2230, 0x1EE1, 0x1B88, 0x1828, 0x14CB,
0x1163, 0x0DF9, 0x0A92, 0x0722, 0x03B3, 0x0047, 0xFCD6, 0xF964,
0xF5FB, 0xF28E, 0xEF23, 0xEBC1, 0xE85C, 0xE4FD, 0xE1A8, 0xDE53,
0xDB03, 0xD7C1, 0xD481, 0xD147, 0xCE1E, 0xCAF6, 0xC7D9, 0xC4CC,
0xC1C4, 0xBEC8, 0xBBDC, 0xB8F9, 0xB622, 0xB35F, 0xB0A4, 0xADF7,
0xAB5B, 0xA8D2, 0xA655, 0xA3E8, 0xA191, 0x9F47, 0x9D0F, 0x9AED,
0x98D9, 0x96D9, 0x94F1, 0x9317, 0x9152, 0x8FA5, 0x8E09, 0x8C82,
0x8B13, 0x89B7, 0x8871, 0x8744, 0x862C, 0x8528, 0x843E, 0x8368,
0x82A9, 0x8204, 0x8174, 0x80FB, 0x809C, 0x8052, 0x8020, 0x8006,
0x8002, 0x8018, 0x8044, 0x8088, 0x80E4, 0x8156, 0x81E1, 0x8283,
0x833B, 0x840B, 0x84F3, 0x85EF, 0x8703, 0x882E, 0x896C, 0x8AC3,
0x8C2F, 0x8DAE, 0x8F46, 0x90F1, 0x92AE, 0x9484, 0x966B, 0x9863,
0x9A73, 0x9C95, 0x9EC5, 0xA10B, 0xA363, 0xA5C6, 0xA840, 0xAACB,
0xAD5F, 0xB007, 0xB2C0, 0xB581, 0xB854, 0xBB34, 0xBE1C, 0xC116,
0xC41C, 0xC727, 0xCA41, 0xCD66, 0xD08E, 0xD3C5, 0xD704, 0xDA44,
0xDD93, 0xE0E6, 0xE43A, 0xE799, 0xEAFC, 0xEE5D, 0xF1C8, 0xF534,
0xF89D, 0xFC0E, 0xFF7F, 0x02EA, 0x065B, 0x09CC, 0x0D32, 0x109E,
0x1406, 0x1764, 0x1AC5, 0x1E20, 0x216F, 0x24BF, 0x2808, 0x2B42,
0x2E7C, 0x31AD, 0x34CF, 0x37ED, 0x3B01, 0x3E04, 0x4102, 0x43F2,
0x46D2, 0x49A9, 0x4C72, 0x4F2A, 0x51D7, 0x5475, 0x56FE, 0x597D,
0x5BEA, 0x5E43, 0x608F, 0x62C9, 0x64EC, 0x6701, 0x6902, 0x6AED,
0x6CC8, 0x6E8E, 0x703C, 0x71D9, 0x7362, 0x74D2, 0x762F, 0x7777,
0x78A6, 0x79C1, 0x7AC5, 0x7BB2, 0x7C8A, 0x7D49, 0x7DF1, 0x7E82,
0x7EFC, 0x7F5F, 0x7FAA, 0x7FDD, 0x7FFA, 0x7FFD, 0x7FEB, 0x7FC0,
0x7F7E, 0x7F24, 0x7EB3, 0x7E2A, 0x7D8B, 0x7CD4, 0x7C04, 0x7B21,
0x7A25, 0x7912, 0x77EC, 0x76AC, 0x7556, 0x73EE, 0x726E, 0x70D9,
0x6F32, 0x6D73, 0x6B9F, 0x69BD, 0x67C2, 0x65B4, 0x6398, 0x6165,
0x5F20, 0x5CCE, 0x5A67, 0x57EE, 0x556B, 0x52D2, 0x502A, 0x4D79,
0x4AB4, 0x47E2, 0x4507, 0x421A, 0x3F23, 0x3C23, 0x3914, 0x35F9,
0x32DB, 0x2FAE, 0x2C77, 0x293F, 0x25F9, 0x22AC, 0x1F5E, 0x1C05,
0x18A7, 0x154A, 0x11E3, 0x0E78, 0x0B12, 0x07A3, 0x0433, 0x00C7,
0xFD56, 0xF9E5, 0xF67C, 0xF30F, 0xEFA2, 0xEC40, 0xE8DB, 0xE57A,
0xE225, 0xDECE, 0xDB7F, 0xD83B, 0xD4F9, 0xD1BF, 0xCE94, 0xCB6C,
0xC84D, 0xC53E, 0xC235, 0xBF36, 0xBC4A, 0xB965, 0xB68B, 0xB3C6,
0xB109, 0xAE5B, 0xABC0, 0xA930, 0xA6B1, 0xA446, 0xA1E8, 0x9F9B,
0x9D65, 0x9B3D, 0x9925, 0x9727, 0x9537, 0x935A, 0x9196, 0x8FE3,
0x8E43, 0x8CBD, 0x8B48, 0x89E9, 0x88A2, 0x8770, 0x8653, 0x854F,
0x845E, 0x8386, 0x82C5, 0x821A, 0x8187, 0x810C, 0x80A8, 0x805B,
0x8026, 0x8008, 0x8001, 0x8013, 0x803C, 0x807D, 0x80D5, 0x8144,
0x81CC, 0x8269, 0x831E, 0x83EC, 0x84CD, 0x85C8, 0x86D9, 0x87FE,
0x893C, 0x8A8F, 0x8BF6, 0x8D75, 0x8F09, 0x90AE, 0x926C, 0x943E,
0x9620, 0x9818, 0x9A25, 0x9C40, 0x9E71, 0xA0B6, 0xA306, 0xA56D,
0xA7E4, 0xAA65, 0xACFC, 0xAFA3, 0xB254, 0xB517, 0xB7E8, 0xBAC3,
0xBDAF, 0xC0A7, 0xC3A4, 0xC6B3, 0xC9CC, 0xCCEA, 0xD016, 0xD34D,
0xD684, 0xD9CA, 0xDD16, 0xE063, 0xE3BC, 0xE71A, 0xEA77, 0xEDDE,
0xF148, 0xF4AE, 0xF81D, 0xFB8D, 0xFEF8, 0x0269, 0x05DB, 0x0944,
0x0CB2, 0x101F, 0x1380, 0x16E5, 0x1A47, 0x1D9C, 0x20F3, 0x2444
};
void S2_vibtonz_en(bool on_off)
{
BRCM_AUDIO_Param_Vibra_t parm_vibra = {0};
aTrace(LOG_AUDIO_CNTLR,
"S2_vibtonz_en: on_off= %d\n", on_off);
if (on_off) {
parm_vibra.strength = s_vibra_strength;
AUDIO_Ctrl_Trigger(ACTION_AUD_EnableByPassVibra,
&parm_vibra, NULL, 0);
} else {
AUDIO_Ctrl_Trigger(ACTION_AUD_DisableByPassVibra, NULL,
NULL, 0);
}
}
void S2_vibtonz_pwm(int nForce)
{
UInt16 *sample_tone_p;
int scale_gain = 0;
int sample_i = 0;
Int32 sample = 0;
aTrace(LOG_AUDIO_CNTLR,
"S2_vibtonz_pwm: strength %d => %d\n", s_vibra_strength, nForce);
if (s_vibra_strength == nForce)
return;
s_vibra_strength = nForce;
if (s_vibra_dma_bufp == NULL)
return;
/* map strength to scale gain and apply to PCM wave table */
scale_gain = s_vibra_strength;
aTrace(LOG_AUDIO_CNTLR, "S2_vibtonz_pwm: scale gain = %d\n",
scale_gain);
sample_tone_p = (UInt16 *)(s_vibra_dma_bufp);
while (sample_i < VIBRA_PERIOD_BYTES) {
sample = *((Int16 *)(sample_tone_p + sample_i));
*(sample_tone_p + sample_i)
= sample*scale_gain/VIBRA_STRENGTH_RANGE;
sample_i++;
}
#if 0
BRCM_AUDIO_Param_Vibra_t parm_vibra = {0};
/* restart the vibration with the new strength*/
AUDIO_Ctrl_Trigger(ACTION_AUD_DisableByPassVibra, NULL,
NULL, 0);
parm_vibra.strength = s_vibra_strength;
AUDIO_Ctrl_Trigger(ACTION_AUD_EnableByPassVibra,
&parm_vibra, NULL, 0);
#endif
}
static void AUDIO_DRIVER_PCM_Vibra_InterruptPeriodCB(void *pPrivate)
{
unsigned long flags;
/*static int count;
if (count%10 == 0)
aTrace(LOG_AUDIO_CNTLR,
"PCM_Vibra_InterruptPeriodCB: count = %d\n", count);
count++;*/
spin_lock_irqsave(&vibra_drv_lock, flags);
if (pcm_vibra_drv_handle)
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle,
AUDIO_DRIVER_BUFFER_READY, NULL);
spin_unlock_irqrestore(&vibra_drv_lock, flags);
}
static void PCM_Vibra_Gen_Start(Int32 strength)
{
unsigned long period_bytes;
unsigned long num_blocks;
unsigned long period_ms;
unsigned long flags;
UInt16 *sample_tone_p;
static AUDIO_DRIVER_CONFIG_t drv_config;
static AUDIO_DRIVER_BUFFER_t pcm_vibra_buf_param;
static dma_addr_t dma_addr;
static AUDIO_SINK_Enum_t spkr;
CSL_CAPH_DEVICE_e aud_dev;
AUDIO_DRIVER_CallBackParams_t cbParams;
sample_tone_p = &sample_tone200_48m[0];
/* open the plyabck device */
aTrace(LOG_AUDIO_CNTLR, "Vibra Audio DDRIVER Open\n");
spin_lock_irqsave(&vibra_drv_lock, flags);
pcm_vibra_drv_handle = AUDIO_DRIVER_Open(AUDIO_DRIVER_PLAY_AUDIO);
spin_unlock_irqrestore(&vibra_drv_lock, flags);
aTrace(LOG_AUDIO_CNTLR, "Vibra Audio DDRIVER Config\n");
/* set the callback */
cbParams.pfCallBack =
AUDIO_DRIVER_PCM_Vibra_InterruptPeriodCB;
cbParams.pPrivateData = (void *)pcm_vibra_drv_handle;
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle, AUDIO_DRIVER_SET_CB,
(void *)&cbParams);
/* configure defaults */
drv_config.sample_rate =
AUDIO_SAMPLING_RATE_48000;
drv_config.num_channel = AUDIO_CHANNEL_MONO;
drv_config.bits_per_sample = 16;
aTrace(LOG_AUDIO_CNTLR, "Config:sr=%u nc=%d bs=%d\n",
drv_config.sample_rate,
drv_config.num_channel,
drv_config.bits_per_sample);
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle, AUDIO_DRIVER_CONFIG,
(void *)&drv_config);
/* set the interrupt period */
period_bytes = VIBRA_PERIOD_BYTES;
num_blocks = 2;
period_ms = (period_bytes * 1000) /
(drv_config.num_channel * 2 * drv_config.sample_rate);
aTrace(LOG_AUDIO_CNTLR,
"Period: ms=%ld bytes=%ld blocks:%ld\n",
period_ms, period_bytes, num_blocks);
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle,
AUDIO_DRIVER_SET_INT_PERIOD,
(void *)&period_bytes);
pcm_vibra_buf_param.buf_size = period_bytes * num_blocks;
if (pcm_vibra_buf_param.pBuf == NULL) {
s_vibra_dma_bufp = pcm_vibra_buf_param.pBuf =
dma_alloc_coherent(NULL, pcm_vibra_buf_param.buf_size,
&dma_addr, GFP_KERNEL);
}
if (pcm_vibra_buf_param.pBuf == NULL) {
aError("Cannot allocate Buffer for Vibra\n");
return;
}
pcm_vibra_buf_param.phy_addr = (UInt32) dma_addr;
aTrace(LOG_AUDIO_CNTLR,
"virt_addr = 0x%x phy_addr=0x%x\n",
(unsigned int)pcm_vibra_buf_param.pBuf,
(unsigned int)dma_addr);
memcpy(pcm_vibra_buf_param.pBuf,
(char *)(sample_tone_p),
pcm_vibra_buf_param.buf_size);
/* set the buffer params */
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle,
AUDIO_DRIVER_SET_BUF_PARAMS,
(void *)&pcm_vibra_buf_param);
/* Start the playback */
spkr = /*AUDIO_SINK_LOUDSPK;*/ AUDIO_SINK_VIBRA;
aud_dev = /*CSL_CAPH_DEV_IHF;*/ CSL_CAPH_DEV_VIBRA;
aTrace(LOG_AUDIO_CNTLR, " Start Vibra Playback\n");
AUDCTRL_EnablePlay(AUDIO_SOURCE_MEM,
spkr,
drv_config.num_channel,
drv_config.sample_rate, &pcm_vibra_path_id);
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle, AUDIO_DRIVER_START,
&aud_dev);
aTrace(LOG_AUDIO_CNTLR, "Vibra Playback started\n");
}
static void PCM_Vibra_Gen_Stop(void)
{
unsigned long flags;
aTrace(LOG_AUDIO_CNTLR, " Stop Vibra playback\n");
AUDIO_DRIVER_Ctrl(pcm_vibra_drv_handle, AUDIO_DRIVER_STOP, NULL);
/* disable the playback path */
AUDCTRL_DisablePlay(AUDIO_SOURCE_MEM,
AUDIO_SINK_VIBRA,
pcm_vibra_path_id);
spin_lock_irqsave(&vibra_drv_lock, flags);
AUDIO_DRIVER_Close(pcm_vibra_drv_handle);
pcm_vibra_drv_handle = NULL;
spin_unlock_irqrestore(&vibra_drv_lock, flags);
}
#endif