/* Description: Kernel AT command handler and gernal purpose controls Parameters cmdIndex -- command index coresponding to AT comand ParamCount -- count of array Params Params -- Parameter array Return 0 on success, -1 otherwise */ int AtAudCtlHandler_put(Int32 cmdIndex, brcm_alsa_chip_t *pChip, Int32 ParamCount, Int32 *Params) { int rtn = 0; aTrace(LOG_AUDIO_DRIVER, "AT-AUD-put ctl=%ld ParamCount= %ld " "[%ld %ld %ld %ld %ld %ld %ld]\n", cmdIndex, ParamCount, Params[0], Params[1], Params[2], Params[3], Params[4], Params[5], Params[6]); switch (cmdIndex) { case AT_AUD_CTL_INDEX: { int count = sizeof(pChip->i32AtAudHandlerParms) / sizeof(pChip->i32AtAudHandlerParms[0]); if (count > ParamCount) count = ParamCount; memcpy(pChip->i32AtAudHandlerParms, Params, sizeof(pChip->i32AtAudHandlerParms[0]) * count); return 0; } case AT_AUD_CTL_DBG_LEVEL: gAudioDebugLevel = Params[0]; return 0; case AT_AUD_CTL_HANDLER: break; default: return -1; } switch (Params[0]) { case AT_AUD_HANDLER_MODE: rtn = AtMaudMode(pChip, ParamCount - 1, &Params[1]); break; case AT_AUD_HANDLER_VOL: rtn = AtMaudVol(pChip, ParamCount - 1, &Params[1]); break; case AT_AUD_HANDLER_TST: rtn = AtMaudTst(pChip, ParamCount - 1, &Params[1]); break; case AT_AUD_HANDLER_LOG: rtn = AtMaudLog(pChip, ParamCount - 1, &Params[1]); break; case AT_AUD_HANDLER_LBTST: rtn = AtMaudLoopback(pChip, ParamCount - 1, &Params[1]); break; default: aWarn( "%s Unsupported handler %ld\n", __func__, Params[0]); rtn = -1; break; } return rtn; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: AUDIO_DRIVER_CaptInterruptPeriodCB * * Description: Playback inteerupt * *------------------------------------------------------------ */ static void AUDIO_DRIVER_CaptInterruptPeriodCB(void *pPrivate) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)pPrivate; AUDIO_DRIVER_HANDLE_t drv_handle; AUDIO_DRIVER_TYPE_t drv_type; struct snd_pcm_runtime *runtime; brcm_alsa_chip_t *pChip = NULL; int substream_number; if (!substream) { aError("Invalid substream 0x%p\n", substream); return; } substream_number = substream->number + CTL_STREAM_PANEL_PCMIN - 1; pChip = snd_pcm_substream_chip(substream); runtime = substream->runtime; if (!runtime) { aError("CaptInterruptPeriodCBInvalid stream=%d runtime 0x%p\n", substream_number, runtime); return; } drv_handle = substream->runtime->private_data; AUDIO_DRIVER_Ctrl(drv_handle, AUDIO_DRIVER_GET_DRV_TYPE, (void *)&drv_type); /* aTrace(LOG_ALSA_INTERFACE, "\n %lx:CaptInterruptPeriodCB drv_type=%d,\n", jiffies, (int)drv_type); */ switch (drv_type) { case AUDIO_DRIVER_CAPT_HQ: case AUDIO_DRIVER_CAPT_VOICE: { /*update the PCM read pointer by period size */ pChip->streamCtl[substream_number].stream_hw_ptr += runtime->period_size; if (pChip->streamCtl[substream_number].stream_hw_ptr > runtime->boundary) pChip->streamCtl[substream_number]. stream_hw_ptr -= runtime->boundary; /*send the period elapsed */ snd_pcm_period_elapsed(substream); /* logmsg_ready(substream, AUD_LOG_PCMIN); */ common_log_capture(AUD_LOG_PCMIN, substream); } break; default: aWarn("CaptInterruptPeriodCB Invalid driver type\n"); break; } return; }
/* Description: AT command handler, handle command AT commands at*maudvol=P1,P2,P3 Parameters: pChip -- Pointer to chip data structure ParamCount -- Count of parameter array Params --- P1,P2,...,P6 */ int AtMaudVol(brcm_alsa_chip_t *pChip, Int32 ParamCount, Int32 *Params) { int *pVolume; int mode, vol; aTrace(LOG_AUDIO_DRIVER, "%s P1-P6=%ld %ld %ld %ld %ld %ld cnt=%ld\n", __func__, Params[0], Params[1], Params[2], Params[3], Params[4], Params[5], ParamCount); csl_caph_ControlHWClock(TRUE); switch (Params[0]) { case 6: /*at*maudvol=6 */ mode = AUDCTRL_GetAudioMode(); /*Get volume. Range -36 ~ 0 dB in Driver and DSP: */ Params[0] = AUDCTRL_GetTelephonySpkrVolume(AUDIO_GAIN_FORMAT_mB); Params[0] = Params[0] / 100; /* dB */ Params[0] += AudParmP()[mode].voice_volume_max; /* Range 0~36 dB shown in PCG */ /* pVolume = pChip->streamCtl[ CTL_STREAM_PANEL_VOICECALL -1].ctlLine[mode].iVolume; Params[0] = pVolume[0]; */ aTrace(LOG_AUDIO_DRIVER, "%s pVolume[0] %ld\n", __func__, Params[0]); return 0; case 7: /* at*maudvol=7,x Range 0~36 dB in PCG */ mode = AUDCTRL_GetAudioMode(); /* mode = pChip->streamCtl[ CTL_STREAM_PANEL_VOICECALL-1].iLineSelect[1]; */ pVolume = pChip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1].ctlLine[mode].iVolume; pVolume[0] = Params[1]; pVolume[1] = Params[1]; vol = Params[1]; vol -= AudParmP()[mode].voice_volume_max; /* Range -36 ~ 0 dB in DSP */ AUDCTRL_SetTelephonySpkrVolume(AUDIO_SINK_UNDEFINED, (vol * 100), AUDIO_GAIN_FORMAT_mB); aTrace(LOG_AUDIO_DRIVER, "%s pVolume[0] %d mode=%d vol %d\n", __func__, pVolume[0], mode, vol); return 0; default: aWarn("%s Unsupported cmd %ld\n", __func__, Params[0]); break; } return -1; }
static void audio_late_resume(struct early_suspend *s) { aTrace(LOG_ALSA_INTERFACE,"audio late resume entered %s", __func__); if (dfs_node_created && during_playback) { int err = 0; err = pi_mgr_dfs_request_update(&dfs_node, PI_PROC_OPP_NORMAL); /* Check if the request was handled or not */ if (err) { aWarn("%s : Warning: could not change the CPU clock to PI_PROC_OPP_NORMAL\n", __func__); } } return; }
int AtMaudMode(brcm_alsa_chip_t *pChip, Int32 ParamCount, Int32 *Params) { AUDIO_SOURCE_Enum_t mic = AUDIO_SOURCE_ANALOG_MAIN; AUDIO_SINK_Enum_t spk = AUDIO_SINK_HANDSET; AudioMode_t mode = AUDIO_SINK_HANDSET; AudioApp_t app = AUDIO_APP_VOICE_CALL, currapp; int rtn = 0; /* 0 means Ok */ static UInt8 loopback_status = 0, loopback_input = 0, loopback_output = 0, sidetone_mode = 0; static UInt8 loopback_api_input, loopback_api_output; Int32 pCurSel[2]; aTrace(LOG_AUDIO_DRIVER, "%s P1-P6=%ld %ld %ld %ld %ld %ld cnt=%ld\n", __func__, Params[0], Params[1], Params[2], Params[3], Params[4], Params[5], ParamCount); csl_caph_ControlHWClock(TRUE); switch (Params[0]) { case 0: /* at*maudmode 0 */ break; case 1: /* at*maudmode 1 mode */ break; case 8: /* at*maudmode=8 */ Params[0] = loopback_status; aTrace(LOG_AUDIO_DRIVER, " %s loopback status is %d\n", __func__, loopback_status); DEBUG(" %s loopback status is %d\n", __func__, loopback_status); break; case 9: /* at*maudmode=9,x. x = 0 --> disable; x =1 enable */ loopback_status = Params[1]; if (loopback_status > 1) loopback_status = 1; aTrace(LOG_AUDIO_DRIVER, " %s set loopback status %d (1:ena 0:dis)\n", __func__, loopback_status); break; case 10: /* at*maudmode=10 --> get loopback path */ /* Per PCG request if (loopback_output > 2) loopback_output = 2; */ Params[0] = loopback_input; Params[1] = loopback_output; aTrace(LOG_AUDIO_DRIVER, "%s loopback path is from src %d to sink %d\n", __func__, loopback_input, loopback_output); break; /* at*maudmode=11,x,y --> set loopback path. */ /* mic: 0 = default mic, 1 = main mic */ /* spk: 0 = handset, 1 = headset, 2 = loud speaker */ case 11: loopback_input = loopback_api_input = Params[1]; loopback_output = loopback_api_output = Params[2]; sidetone_mode = Params[3]; if (((loopback_input > 6) && (loopback_input != 11)) || ((loopback_output > 2) && (loopback_output != 9) && (loopback_output != 4))) { aError( "%s srr/sink exceeds its range.\n", __func__); rtn = -1; break; } if (loopback_output == 2) /* use IHF */ loopback_api_output = 4; if (loopback_input == 0) /* default mic: use main mic */ loopback_api_input = 1; loopback_status = 1; /* enable the HW loopback without DSP. */ AUDCTRL_SetAudioLoopback(TRUE, loopback_api_input, loopback_api_output, sidetone_mode); aTrace(LOG_AUDIO_DRIVER, "%s ena lpback: src %d sink %d sidetone %d\n", __func__, loopback_api_input, loopback_api_output, sidetone_mode); break; case 12: /* at*maudmode=12 --> disable loopback path */ loopback_status = 0; AUDCTRL_SetAudioLoopback(FALSE, loopback_api_input, loopback_api_output, sidetone_mode); aTrace(LOG_AUDIO_DRIVER, "%s dis lpback: src %d sink %d sidetone %d\n", __func__, loopback_api_input, loopback_api_output, sidetone_mode); break; case 13: /* at*maudmode=13 --> Get call ID */ aError( "%s get call ID is not supported\n", __func__); rtn = -1; break; /* at*maudmode=14 --> read current mode and app */ case 14: Params[0] = AUDCTRL_GetAudioApp(); Params[1] = AUDCTRL_GetAudioMode(); aTrace(LOG_AUDIO_DRIVER, "%s app %ld mode %ld\n", __func__, Params[0], Params[1]); break; /* at*maudmode=15 --> set current mode and app */ case 15: app = Params[1]; mode = Params[2]; AUDCTRL_GetSrcSinkByMode(mode, &mic, &spk); pCurSel[0] = pChip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1].iLineSelect[0]; /* save current setting */ pCurSel[1] = pChip-> streamCtl[CTL_STREAM_PANEL_VOICECALL - 1].iLineSelect[1]; /* Update 'VC-SEL' -- */ pChip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1]. iLineSelect[0] = mic; pChip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1]. iLineSelect[1] = spk; #ifdef CONFIG_BCM_MODEM RPC_SetProperty(RPC_PROP_AUDIO_MODE, (UInt32)(app * AUDIO_MODE_NUMBER + mode)); #endif /* for PCG to set new app */ currapp = AUDCTRL_GetAudioApp(); if (currapp != app) { /* Remove the current app before setting the new app */ AUDCTRL_RemoveAudioApp(currapp); AUDCTRL_SaveAudioApp(app); } if (app == AUDIO_APP_VOICE_CALL || app == AUDIO_APP_VOICE_CALL_WB || app == AUDIO_APP_VT_CALL || app == AUDIO_APP_VT_CALL_WB) { AUDCTRL_SetTelephonyMicSpkr(mic, spk, false); AUDCTRL_SetAudioMode(mode, app); } else if (app == AUDIO_APP_MUSIC) { if (AUDCTRL_InVoiceCall() == FALSE) { AUDCTRL_SwitchPlaySpk_forTuning(mode); AUDCTRL_SaveAudioMode(mode); AUDCTRL_SaveAudioApp(app); } } else { /* Handling all other apps cases */ /* For PCG to set new Mode */ AUDCTRL_SetAudioMode(mode, app); } aTrace(LOG_AUDIO_DRIVER, "%s mic %d spk %d mode %ld app %ld\n", __func__, mic, spk, Params[2], Params[1]); break; /* read back AUDIO_APP_NUMBER and AUDIO_APP_MM_NUMBER */ /* needs to match to enum AudioTuneCommand_t in at_audtune.c */ case 16: Params[0] = AUDIO_APP_NUMBER; Params[1] = AUDIO_APP_MM_NUMBER; break; case 99: /* at*maudmode=99 --> stop tuning */ break; /* at*maudmode=100 --> set external audio amplifer gain in PMU */ /* PCG and loadcal currently use Q13p2 gain format */ case 100: { short gain; gain = (short)Params[3]; if (Params[1] == 3) { aTrace(LOG_AUDIO_DRIVER, "Params[2] = %d, " "Params[3] %d, audio mode %d\n", (int)Params[2], (int)Params[3], AUDCTRL_GetAudioMode()); if ((Params[2] == PARAM_PMU_SPEAKER_PGA_LEFT_CHANNEL) || (Params[2] == PARAM_PMU_SPEAKER_PGA_RIGHT_CHANNEL)) { if (AUDCTRL_GetAudioMode() == AUDIO_MODE_HEADSET || AUDCTRL_GetAudioMode() == AUDIO_MODE_TTY) { aTrace(LOG_AUDIO_DRIVER, "%s ext headset " "speaker gain = %d\n", __func__, gain); if (Params[2] == PARAM_PMU_SPEAKER_PGA_LEFT_CHANNEL) extern_hs_set_gain(gain*25, AUDIO_HS_LEFT); else if (Params[2] == PARAM_PMU_SPEAKER_PGA_RIGHT_CHANNEL) extern_hs_set_gain(gain*25, AUDIO_HS_RIGHT); } else if (AUDCTRL_GetAudioMode() == AUDIO_MODE_SPEAKERPHONE) { aTrace(LOG_AUDIO_DRIVER, "%s ext IHF " "speaker gain = %d\n", __func__, gain); extern_ihf_set_gain(gain*25); } } /* Params[2] checking */ aTrace(LOG_AUDIO_DRIVER, "Params[2] = %d, Params[3] %d," " audio mode %d\n", (int)Params[2], (int)Params[3], AUDCTRL_GetAudioMode()); if (Params[2] == PARAM_PMU_HIGH_GAIN_MODE_FLAG) { if (AUDCTRL_GetAudioMode() == AUDIO_MODE_SPEAKERPHONE) { aTrace(LOG_AUDIO_DRIVER, "ext IHF high gain " "mode = %d\n", (int)Params[3]); extern_ihf_en_hi_gain_mode( (int)Params[3]); } else if (AUDCTRL_GetAudioMode() == AUDIO_MODE_HEADSET || AUDCTRL_GetAudioMode() == AUDIO_MODE_TTY) { aTrace(LOG_AUDIO_DRIVER, "ext HS high gain " "mode = %d\n", (int)Params[3]); extern_hs_en_hi_gain_mode( (int)Params[3]); } } } /* if (Params[1] == 3) */ } /* case 100 */ break; default: aWarn("%s Unsupported cmd %ld\n", __func__, Params[0]); rtn = -1; break; } return rtn; }
/**************************************************************************** * * Function Name:CSL_CAPH_SWITCH_STATUS_e csl_caph_switch_config_channel( * CSL_CAPH_SWITCH_CONFIG_t chnl_config) * * Description: configure CAPH switch channel * ****************************************************************************/ CSL_CAPH_SWITCH_STATUS_e csl_caph_switch_config_channel(CSL_CAPH_SWITCH_CONFIG_t chnl_config) { CAPH_SWITCH_CHNL_e chal_chnl = CAPH_SWITCH_CH_VOID; CAPH_DATA_FORMAT_e chal_dataFormat = CAPH_MONO_16BIT; CAPH_SWITCH_TRIGGER_e chal_trig = CAPH_VOID; CAPH_DST_STATUS_e dstStatus = CAPH_DST_OK; CSL_CAPH_SWITCH_STATUS_e status = CSL_CAPH_SWITCH_OWNER; aTrace(LOG_AUDIO_CSL, "csl_caph_switch_config_channel:: chnl = 0x%x, srcAddr = " "0x%lx, dstcAddr = 0x%lx, dataFmt = 0x%x, trigger = 0x%x\n", chnl_config.chnl, chnl_config.FIFO_srcAddr, chnl_config.FIFO_dstAddr, chnl_config.dataFmt, chnl_config.trigger); /* Get cHAL Channel */ chal_chnl = csl_caph_switch_get_chalchnl(chnl_config.chnl); /* Select Source for this channel */ chal_caph_switch_select_src(handle, chal_chnl, (UInt16) (chnl_config.FIFO_srcAddr)); /* Add Dst for this channel */ dstStatus = chal_caph_switch_add_dst(handle, chal_chnl, (UInt16) (chnl_config.FIFO_dstAddr)); csl_caph_switch_setDSTStatus(chal_chnl, dstStatus); /* If the DST is already being used by other channels * Do not set the switch channel anymore. */ if (dstStatus != CAPH_DST_OK) { audio_xassert(0, dstStatus); aWarn("%s::sw %d dst 0x%lx used by other sw\n", __func__, chnl_config.chnl, chnl_config.FIFO_dstAddr); chal_caph_switch_free_channel(handle, chal_chnl); status = CSL_CAPH_SWITCH_BORROWER; return status; } /* Set data format */ switch (chnl_config.dataFmt) { case CSL_CAPH_16BIT_MONO: chal_dataFormat = CAPH_MONO_16BIT; break; case CSL_CAPH_16BIT_STEREO: chal_dataFormat = CAPH_STEREO_16BIT; break; case CSL_CAPH_24BIT_MONO: chal_dataFormat = CAPH_MONO_24BIT; break; case CSL_CAPH_24BIT_STEREO: chal_dataFormat = CAPH_STEREO_24BIT; break; default: audio_xassert(0, chnl_config.dataFmt); } chal_caph_switch_set_datafmt(handle, chal_chnl, chal_dataFormat); /* Select the trigger */ chal_trig = chnl_config.trigger; chal_caph_switch_select_trigger(handle, chal_chnl, chal_trig); return status; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackTrigger * * Description: Command handling function * *------------------------------------------------------------ */ static int PcmPlaybackTrigger(struct snd_pcm_substream *substream, int cmd) { int ret = 0; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); AUDIO_DRIVER_HANDLE_t drv_handle; int substream_number = substream->number; s32 *pSel; int i, count = 0; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH PcmPlaybackTrigger stream=%d, cmd %d, start_threshold %ld\n", substream_number, cmd, substream->runtime->start_threshold); callMode = chip->iCallMode; drv_handle = substream->runtime->private_data; pSel = chip->streamCtl[substream_number].iLineSelect; for (i = 0; i < MAX_PLAYBACK_DEV; i++) { chip->streamCtl[substream_number].dev_prop.p[i].source = AUDIO_SOURCE_MEM; chip->streamCtl[substream_number].dev_prop.p[i].sink = AUDIO_SINK_UNDEFINED; } if (AUDCTRL_GetMFDMode() && (chip->streamCtl[substream_number].iLineSelect[0] == AUDIO_SINK_VIBRA)) { /*With MFD, vibra plays to IHF, and it does not mix with voice even in call mode */ chip->streamCtl[substream_number].dev_prop.p[0].sink = AUDIO_SINK_LOUDSPK; } else if ((callMode == MODEM_CALL) && (chip->streamCtl[substream_number].iLineSelect[0] != AUDIO_SINK_I2S)) { /*call mode & not FM Tx playback */ chip->streamCtl[substream_number].dev_prop.p[0].source = AUDIO_SOURCE_MEM; chip->streamCtl[substream_number].dev_prop.p[0].sink = AUDIO_SINK_DSP; } else { for (i = 0; i < MAX_PLAYBACK_DEV; i++) { if (pSel[i] >= AUDIO_SINK_HANDSET && pSel[i] < AUDIO_SINK_VALID_TOTAL) { chip->streamCtl[substream_number].dev_prop.p[i]. sink = pSel[i]; } else { /* No valid device in the list to do a playback, * return error */ if (++count == MAX_PLAYBACK_DEV) { aError("No device selected by" " the user ?\n"); return -EINVAL; } else chip->streamCtl[substream_number]. dev_prop.p[i].sink = AUDIO_SINK_UNDEFINED; } } } switch (cmd) { case SNDRV_PCM_TRIGGER_START: { BRCM_AUDIO_Param_Start_t param_start; BRCM_AUDIO_Param_Spkr_t param_spkr; BRCM_AUDIO_Param_Second_Dev_t param_second_spkr; struct snd_pcm_runtime *runtime = substream->runtime; if (dfs_node_created) { int err = 0; err = pi_mgr_dfs_request_update(&dfs_node, PI_PROC_OPP_NORMAL); /* Check if the request was handled or not */ if (err) { aWarn("%s : Warning: could not change the CPU clock to PI_PROC_OPP_NORMAL\n", __func__); } during_playback = TRUE; } param_start.drv_handle = drv_handle; param_start.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_start.channels = runtime->channels; param_start.rate = runtime->rate; param_start.vol[0] = chip->streamCtl[substream_number].ctlLine[pSel[0]]. iVolume[0]; param_start.vol[1] = chip->streamCtl[substream_number].ctlLine[pSel[0]]. iVolume[1]; param_start.stream = substream_number; param_second_spkr.source = AUDIO_SOURCE_UNDEFINED; param_second_spkr.sink = AUDIO_SINK_VALID_TOTAL; param_second_spkr.pathID = 0; param_second_spkr.substream_number = substream_number; /*the for loop starts with p[1], the second channel. */ for (i = 1; i < MAX_PLAYBACK_DEV; i++) { AUDIO_SINK_Enum_t sink = chip->streamCtl[substream_number].dev_prop.p[i].sink; /*to support short tone to stereo IHF + headset, only care these sinks*/ if (sink == AUDIO_SINK_HEADSET || sink == AUDIO_SINK_HEADPHONE || sink == AUDIO_SINK_LOUDSPK) { param_second_spkr.source = chip->streamCtl[substream_number]. dev_prop.p[i].source; param_second_spkr.sink = chip->streamCtl[substream_number]. dev_prop.p[i].sink; } } AUDCTRL_SetSecondSink(param_second_spkr); AUDIO_Ctrl_Trigger(ACTION_AUD_StartPlay, ¶m_start, NULL, 0); for (i = 1; i < MAX_PLAYBACK_DEV; i++) { if (chip->streamCtl[substream_number].dev_prop. p[i].sink != AUDIO_SINK_UNDEFINED) { param_spkr.src = chip->streamCtl[substream_number]. dev_prop.p[i].source; param_spkr.sink = chip->streamCtl[substream_number]. dev_prop.p[i].sink; param_spkr.stream = substream_number; AUDIO_Ctrl_Trigger (ACTION_AUD_AddChannel, ¶m_spkr, NULL, 0); } } } break; case SNDRV_PCM_TRIGGER_STOP: { BRCM_AUDIO_Param_Stop_t param_stop; struct completion *compl_ptr; if (dfs_node_created) { int err = 0; err = pi_mgr_dfs_request_update(&dfs_node, PI_PROC_OPP_ECONOMY1); /* Check if the request was handled or not */ if (err) { aWarn("%s : Warning: could not change the CPU clock to PI_PROC_OPP_ECONOMY1\n", __func__); } during_playback = FALSE; } param_stop.drv_handle = drv_handle; param_stop.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_stop.stream = substream_number; aTrace (LOG_ALSA_INTERFACE, "ACTION_AUD_StopPlay stream=%d\n", param_stop.stream); compl_ptr = &chip->streamCtl[substream_number] .stopCompletion; init_completion(compl_ptr); chip->streamCtl[substream_number].pStopCompletion = compl_ptr; AUDIO_Ctrl_Trigger(ACTION_AUD_StopPlay, ¶m_stop, CtrlStopCB, (int)compl_ptr); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: { BRCM_AUDIO_Param_Pause_t param_pause; param_pause.drv_handle = drv_handle; param_pause.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_pause.stream = substream_number; AUDIO_Ctrl_Trigger(ACTION_AUD_PausePlay, ¶m_pause, NULL, 0); } break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: { BRCM_AUDIO_Param_Resume_t param_resume; struct snd_pcm_runtime *runtime = substream->runtime; param_resume.drv_handle = drv_handle; param_resume.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_resume.channels = runtime->channels; param_resume.rate = runtime->rate; param_resume.stream = substream_number; AUDIO_Ctrl_Trigger(ACTION_AUD_ResumePlay, ¶m_resume, NULL, 0); } break; default: return -EINVAL; } return ret; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackOpen * * Description: Open PCM playback device * *------------------------------------------------------------ */ static int PcmPlaybackOpen(struct snd_pcm_substream *substream) { AUDIO_DRIVER_HANDLE_t drv_handle; BRCM_AUDIO_Param_Open_t param_open; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err = 0; int substream_number = substream->number; aTrace (LOG_ALSA_INTERFACE, "ALSA-CAPH %lx:playback_open stream=%d," "PCM_TOTAL_BUF_BYTES=%d chip->iEnablePhoneCall=%d," "speaker=%d\n", jiffies, substream_number, PCM_TOTAL_BUF_BYTES, (unsigned int)chip->iEnablePhoneCall, chip->streamCtl[substream_number].iLineSelect[0]); if (!dfs_node_created) { int err = 0; err = pi_mgr_dfs_add_request(&dfs_node, audio_dfs, PI_MGR_PI_ID_ARM_CORE, PI_MGR_DFS_MIN_VALUE); /* Check if the request was handled or not */ if (err) { aWarn("%s : Warning: could not create audio dfs_node\n", __func__); } dfs_node_created = TRUE; } #ifdef CONFIG_HAS_EARLYSUSPEND if (!early_suspend_registered) { register_early_suspend(&audio_early_suspend_desc); early_suspend_registered = TRUE; } #endif /* CONFIG_HAS_EARLYSUSPEND */ param_open.drv_handle = NULL; param_open.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_open.stream = substream_number; aTrace(LOG_ALSA_INTERFACE, "\n %lx:playback_open route the playback to CAPH\n", jiffies); /*route the playback to CAPH */ runtime->hw = brcm_playback_hw; chip->streamCtl[substream_number].dev_prop.p[0].drv_type = AUDIO_DRIVER_PLAY_AUDIO; chip->streamCtl[substream_number].pSubStream = substream; #if defined(DYNAMIC_DMA_PLAYBACK) runtime->hw.periods_max = 8; #endif /*open the playback device */ AUDIO_Ctrl_Trigger(ACTION_AUD_OpenPlay, ¶m_open, NULL, 1); drv_handle = param_open.drv_handle; if (drv_handle == NULL) { aError("\n %lx:playback_open stream=%d failed\n", jiffies, substream_number); return -1; } substream->runtime->private_data = drv_handle; aTrace(LOG_ALSA_INTERFACE, "chip-0x%lx substream-0x%lx drv_handle-0x%lx\n", (UInt32) chip, (UInt32) substream, (UInt32) drv_handle); return err; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: AUDIO_DRIVER_InterruptPeriodCB * * Description: Callback funtion when DMA done, running at * worker thread context (worker_audio_playback) * *------------------------------------------------------------ */ static void AUDIO_DRIVER_InterruptPeriodCB(void *pPrivate) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)pPrivate; AUDIO_DRIVER_HANDLE_t drv_handle; AUDIO_DRIVER_TYPE_t drv_type; struct snd_pcm_runtime *runtime; brcm_alsa_chip_t *pChip = NULL; int stream_id = 0; if (!substream) { aError("Invalid substream 0x%p\n", substream); return; } pChip = snd_pcm_substream_chip(substream); runtime = substream->runtime; if (!runtime) { aError("InterruptPeriodCBInvalid runtime 0x%p\n", runtime); return; } drv_handle = substream->runtime->private_data; AUDIO_DRIVER_Ctrl(drv_handle, AUDIO_DRIVER_GET_DRV_TYPE, (void *)&drv_type); stream_id = StreamIdOfDriver(drv_handle); BUG_ON(stream_id < CSL_CAPH_STREAM_NONE || stream_id >= CSL_CAPH_STREAM_TOTAL); switch (drv_type) { case AUDIO_DRIVER_PLAY_VOICE: case AUDIO_DRIVER_PLAY_AUDIO: case AUDIO_DRIVER_PLAY_RINGER: { /*update the PCM read pointer by period size */ int offset = runtime->period_size; #if defined(DYNAMIC_DMA_PLAYBACK) /*period_size is actually the copy size at dyndma mode*/ int dmaSize = csl_audio_render_get_dma_size(stream_id); if (dmaSize != 0) offset = bytes_to_frames(runtime, dmaSize); #endif pChip->streamCtl[substream->number].stream_hw_ptr += offset; if (pChip->streamCtl[substream->number].stream_hw_ptr > runtime->boundary) pChip->streamCtl[substream->number]. stream_hw_ptr -= runtime->boundary; /* send the period elapsed */ snd_pcm_period_elapsed(substream); /* logmsg_ready(substream, AUD_LOG_PCMOUT); */ common_log_capture(AUD_LOG_PCMOUT, substream); } break; default: aWarn("InterruptPeriodCB Invalid driver type\n"); break; } return; }