/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackPointer * * Description: Get playback pointer in frames * *------------------------------------------------------------ */ static snd_pcm_uframes_t PcmPlaybackPointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); pos = chip->streamCtl[substream->number].stream_hw_ptr; #if defined(DYNAMIC_DMA_PLAYBACK) /*draining requires all buffer to be consumed. aplay needs this to finish properly*/ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && (pos + runtime->period_size) < runtime->control->appl_ptr) { BRCM_AUDIO_Param_BufferReady_t param; /*aTrace(LOG_ALSA_INTERFACE, "%s stream %d read %x write %x\n", __func__, substream->number, (int)pos, (int)runtime->control->appl_ptr);*/ param.drv_handle = substream->runtime->private_data; param.stream = substream->number; param.size = 0; param.offset = 0; AUDIO_Ctrl_Trigger(ACTION_AUD_BufferReady, ¶m, NULL, 0); } #endif pos %= runtime->buffer_size; return pos; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackPrepare * * Description: Prepare PCM playback device, next call is Trigger or Close * *------------------------------------------------------------ */ static int PcmPlaybackPrepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); BRCM_AUDIO_Param_Prepare_t parm_prepare; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH playback_prepare " "stream=%d period=%d period_size=%d," "bufsize=%d start_threshold=%ld stop_threshold=%ld" " frame_bits %d rate=%d ch=%d\n", substream->number, (int)runtime->periods, (int)runtime->period_size, (int)runtime->buffer_size, runtime->start_threshold, runtime->stop_threshold, runtime->frame_bits, runtime->rate, runtime->channels); chip->streamCtl[substream->number].stream_hw_ptr = 0; parm_prepare.drv_handle = substream->runtime->private_data; parm_prepare.cbParams.pfCallBack = AUDIO_DRIVER_InterruptPeriodCB; parm_prepare.cbParams.pPrivateData = (void *)substream; parm_prepare.period_count = runtime->periods; parm_prepare.period_bytes = frames_to_bytes(runtime, runtime->period_size); parm_prepare.buf_param.buf_size = runtime->dma_bytes; /*virtual address */ parm_prepare.buf_param.pBuf = runtime->dma_area; /* physical address */ parm_prepare.buf_param.phy_addr = (UInt32) (runtime->dma_addr); aTrace(LOG_ALSA_INTERFACE, "buf_size = %d pBuf=0x%lx phy_addr=0x%x\n", runtime->dma_bytes, (UInt32) runtime->dma_area, runtime->dma_addr); parm_prepare.drv_config.sample_rate = runtime->rate; parm_prepare.drv_config.num_channel = runtime->channels; parm_prepare.drv_config.bits_per_sample = 16; parm_prepare.drv_config.instanceId = substream->number; parm_prepare.drv_config.arm2sp_mixMode = chip->pi32SpeechMixOption[substream->number]; parm_prepare.stream = substream->number; AUDIO_Ctrl_Trigger(ACTION_AUD_SetPrePareParameters, &parm_prepare, NULL, 0); /* DEBUG("\n%lx:playback_prepare period bytes=%d, periods =%d, buffersize=%d\n",jiffies, g_brcm_alsa_chip->period_bytes[0], runtime->periods, runtime->dma_bytes); */ return 0; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmCapturePrepare * * Description: Prepare hardware to capture * *------------------------------------------------------------ */ static int PcmCapturePrepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); int substream_number = substream->number + CTL_STREAM_PANEL_PCMIN - 1; BRCM_AUDIO_Param_Prepare_t parm_prepare; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH %lx:capture_prepare: stream=%d rate =%d," "format =%d channel=%d dma_area=0x%x dma_bytes=%d," "period_bytes=%d avail_min=%d periods=%d buffer_size=%d\n", jiffies, substream_number, runtime->rate, runtime->format, runtime->channels, (unsigned int)runtime->dma_area, runtime->dma_bytes, frames_to_bytes(runtime, runtime->period_size), frames_to_bytes(runtime, runtime->control->avail_min), runtime->periods, (int)runtime->buffer_size); chip->streamCtl[substream_number].stream_hw_ptr = 0; parm_prepare.drv_handle = substream->runtime->private_data; parm_prepare.cbParams.pfCallBack = AUDIO_DRIVER_CaptInterruptPeriodCB; parm_prepare.cbParams.pPrivateData = (void *)substream; parm_prepare.period_count = runtime->periods; parm_prepare.period_bytes = frames_to_bytes(runtime, runtime->period_size); parm_prepare.buf_param.buf_size = runtime->dma_bytes; /* virtual address */ parm_prepare.buf_param.pBuf = runtime->dma_area; /* physical address */ parm_prepare.buf_param.phy_addr = (UInt32) (runtime->dma_addr); aTrace(LOG_ALSA_INTERFACE, "buf_size = %d pBuf=0x%lx phy_addr=0x%x\n", runtime->dma_bytes, (UInt32) runtime->dma_area, runtime->dma_addr); parm_prepare.drv_config.sample_rate = runtime->rate; parm_prepare.drv_config.num_channel = runtime->channels; parm_prepare.drv_config.bits_per_sample = 16; parm_prepare.stream = substream_number; AUDIO_Ctrl_Trigger(ACTION_AUD_SetPrePareParameters, &parm_prepare, NULL, 0); return 0; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmCaptureClose * * Description: Close PCM capure device * *------------------------------------------------------------ */ static int PcmCaptureClose(struct snd_pcm_substream *substream) { BRCM_AUDIO_Param_Close_t param_close; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); int substream_number = substream->number + CTL_STREAM_PANEL_PCMIN - 1; param_close.drv_handle = substream->runtime->private_data; param_close.stream = substream_number; /*close the driver */ AUDIO_Ctrl_Trigger(ACTION_AUD_CloseRecord, ¶m_close, NULL, 1); substream->runtime->private_data = NULL; chip->streamCtl[substream_number].pSubStream = NULL; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH %lx:capture_close stream=%d\n", jiffies, substream_number); return 0; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmPlaybackClose * * Description: Close PCM playback device * *------------------------------------------------------------ */ static int PcmPlaybackClose(struct snd_pcm_substream *substream) { BRCM_AUDIO_Param_Close_t param_close; brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH %lx:playback_close stream=%d\n", jiffies, substream->number); param_close.drv_handle = substream->runtime->private_data; param_close.stream = substream->number; /*close the driver */ AUDIO_Ctrl_Trigger(ACTION_AUD_ClosePlay, ¶m_close, NULL, 1); substream->runtime->private_data = NULL; chip->streamCtl[substream->number].pSubStream = NULL; return 0; }
//***************************************************************** // Functiona Name: SetControlItem // // Description: Set control item, will set hardware if value changed. // //***************************************************************** static int SetControlItem( struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol ) { int changed = 0; int vol = 0; int mute = 0; audio_init(); //DEBUG("\n%lx:SetControlItem",jiffies); if(kcontrol->private_value>=0 && kcontrol->private_value<BRCM_CTL_TOTAL) { if(!(kcontrol->private_value&1))//volume { DEBUG("\n%lx:SetControlItem [%s]=%d",jiffies, gpstrCtrlName[kcontrol->private_value], (int)ucontrol->value.integer.value[0]); if((gCurPath != kcontrol->private_value) && (BRCM_CTL_Mic_Capture_Volume!=kcontrol->private_value)) //gCurPath is for playback only { //Enable path with volume DEBUG("\n%lx:SetControlItem path = %d changed to %d\n",jiffies, (int)gCurPath, (int)kcontrol->private_value); sgBrcmCtrlVal[kcontrol->private_value] = ucontrol->value.integer.value[0] ; changed=1; gCurPath = kcontrol->private_value; } if(sgBrcmCtrlVal[kcontrol->private_value] != ucontrol->value.integer.value[0] ) { sgBrcmCtrlVal[kcontrol->private_value] = ucontrol->value.integer.value[0] ; // audvoc_configure_Volume(0, 0x1FF) ; changed=1; } DEBUG("SetControlItem: sgBrcmCtrlVal[%d] = %d\n", kcontrol->private_value, sgBrcmCtrlVal[kcontrol->private_value] ); } else //mute { DEBUG("\n%lx:mute SetControlItem [%s]=%d",jiffies, gpstrCtrlName[kcontrol->private_value], (int)ucontrol->value.integer.value[0]); //if(sgBrcmCtrlVal[kcontrol->private_value] != ucontrol->value.integer.value[0] ) { sgBrcmCtrlVal[kcontrol->private_value] = ucontrol->value.integer.value[0] ; changed=1; } } if(changed) { DEBUG("\n SET SetControlItem [%s]=%d", gpstrCtrlName[kcontrol->private_value], (int)ucontrol->value.integer.value[0]); switch(kcontrol->private_value) { case BRCM_CTL_EAR_Playback_Volume: { vol = (int)ucontrol->value.integer.value[0]; // ensure that it is not completely muted at the minimum volume level if(vol > 5) vol = 5; AUDCTRL_SetPlayVolume(AUDIO_HW_VOICE_OUT,AUDCTRL_SPK_HANDSET,AUDIO_GAIN_FORMAT_DSP_VOICE_VOL_GAIN,vol,vol); } break; case BRCM_CTL_Speaker_Playback_Volume: { unsigned int vol; vol = (int)ucontrol->value.integer.value[0]; if (vol == 0) { vol = AUDIO_VOLUME_FM_MUTE; // for mute case send 0xff to distinguish from other values. } else { vol = vol -1; // volume range is converted from 15-1 to 14-0 } //if we are to set volume for FM app then apply FM app gain table AUDCTRL_SetPlayVolume(AUDIO_HW_AUDIO_OUT,AUDCTRL_SPK_LOUDSPK, AUDIO_GAIN_FORMAT_FM_RADIO_DIGITAL_VOLUME_TABLE, vol, vol); DEBUG("Set FM Play vol to %d\n",vol); } break; case BRCM_CTL_Mic_Capture_Mute: { mute = (int)ucontrol->value.integer.value[0]; AUDCTRL_SetTelephonyMicMute(AUDIO_HW_VOICE_OUT,AUDCTRL_MIC_MAIN,mute); } break; case BRCM_CTL_ROUTE: { BRCM_AUDIO_Param_Route_t parm_route; parm_route.command = (int)ucontrol->value.integer.value[0]; parm_route.speaker = (int)ucontrol->value.integer.value[1]; // Send the route command AUDIO_Ctrl_Trigger(ACTON_ROUTE,&parm_route,NULL,0); } break; default: break; } } } return changed; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmCaptureTrigger * * Description: Command handling function * *------------------------------------------------------------ */ static int PcmCaptureTrigger(struct snd_pcm_substream *substream, int cmd /*commands to handle */) { brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream); AUDIO_DRIVER_HANDLE_t drv_handle; s32 *pSel; int substream_number = substream->number + CTL_STREAM_PANEL_PCMIN - 1; int ret; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH %lx:capture_trigger stream=%d cmd=%d\n", jiffies, substream_number, cmd); callMode = chip->iCallMode; drv_handle = substream->runtime->private_data; pSel = chip->streamCtl[substream_number].iLineSelect; if (pSel[0] >= AUDIO_SOURCE_ANALOG_MAIN && pSel[0] < AUDIO_SOURCE_VALID_TOTAL) { chip->streamCtl[substream_number].dev_prop.c.source = pSel[0]; } else { aError ("Error!! No valid device selected by the user," " pSel[0]=%d\n", pSel[0]); return -EINVAL; } switch (cmd) { case SNDRV_PCM_TRIGGER_START: { BRCM_AUDIO_Param_Start_t param_start; struct snd_pcm_runtime *runtime = substream->runtime; param_start.drv_handle = drv_handle; param_start.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_start.channels = runtime->channels; param_start.stream = substream_number; if (callMode == MODEM_CALL) /*record Mode */ param_start.mixMode = chip->pi32SpeechMixOption[substream_number]; else /* In Idle mode */ param_start.mixMode = 0; param_start.rate = runtime->rate; param_start.callMode = callMode; if ((substream_number + 1) == CTL_STREAM_PANEL_PCMIN) chip->streamCtl[substream_number].dev_prop.c. sink = AUDIO_SINK_MEM; else if ((substream_number + 1) == CTL_STREAM_PANEL_SPEECHIN) chip->streamCtl[substream_number].dev_prop.c. sink = AUDIO_SINK_DSP; 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]; aTrace(LOG_ALSA_INTERFACE, "ACTION_AUD_StartRecord," "stream=%d, mixMode %ld\n", param_start.stream, param_start.mixMode); ret = AUDIO_Ctrl_Trigger(ACTION_AUD_StartRecord, ¶m_start, NULL, 0); if (ret == RESULT_ERROR) { if (chip->streamCtl[substream_number]. pStopCompletion) complete( chip->streamCtl[substream_number]. pStopCompletion); chip->streamCtl[substream_number].pStopCompletion = NULL; return -1; } } break; case SNDRV_PCM_TRIGGER_STOP: { BRCM_AUDIO_Param_Stop_t param_stop; struct completion *compl_ptr; param_stop.drv_handle = drv_handle; param_stop.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_stop.stream = substream_number; param_stop.callMode = callMode; aTrace(LOG_ALSA_INTERFACE, "ACTION_AUD_StopRecord," "stream=%d, callMode %ld\n", param_stop.stream, param_stop.callMode); compl_ptr = &chip->streamCtl[substream_number] .stopCompletion; init_completion(compl_ptr); chip->streamCtl[substream_number].pStopCompletion = compl_ptr; ret = AUDIO_Ctrl_Trigger(ACTION_AUD_StopRecord, ¶m_stop, CtrlStopCB, (int)compl_ptr); if (ret == RESULT_ERROR) { complete(compl_ptr); chip->streamCtl[substream_number].pStopCompletion = NULL; } } break; default: return -EINVAL; } return 0; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * Function Name: PcmCaptureOpen * * Description: Open PCM capure device * *------------------------------------------------------------ */ static int PcmCaptureOpen(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; /* for indexing */ int substream_number = substream->number + CTL_STREAM_PANEL_PCMIN - 1; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH PcmCaptureOpen stream=%d\n", substream_number); callMode = chip->iCallMode; if ((substream_number + 1) == CTL_STREAM_PANEL_PCMIN) { chip->streamCtl[substream_number].dev_prop.c.drv_type = AUDIO_DRIVER_CAPT_HQ; runtime->hw = brcm_capture_hw; /* Lets make it a multiple of 4k */ err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096); err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &pcm_capture_period_bytes_constraints_list); if (err < 0) return err; } else if ((substream_number + 1) == CTL_STREAM_PANEL_SPEECHIN) { chip->streamCtl[substream_number].dev_prop.c.drv_type = AUDIO_DRIVER_CAPT_VOICE; runtime->hw = brcm_voice_capture_hw; /* should be multiple of SM size (16K support) */ err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2560); err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &pcm_voice_capture_period_bytes_constraints_list); if (err < 0) return err; } /*open the capture device */ param_open.drv_handle = NULL; param_open.pdev_prop = &chip->streamCtl[substream_number].dev_prop; param_open.stream = substream_number; /*for capture */ chip->streamCtl[substream_number].pSubStream = substream; AUDIO_Ctrl_Trigger(ACTION_AUD_OpenRecord, ¶m_open, NULL, 1); drv_handle = param_open.drv_handle; if (drv_handle == NULL) { aError("\n %lx:capture_open stream=%d failed\n", jiffies, substream_number); return -1; } substream->runtime->private_data = drv_handle; aTrace(LOG_ALSA_INTERFACE, "\n %lx:capture_open stream=%d\n", jiffies, substream_number); return 0; }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++ * * 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; }
int PcmPlaybackCopy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count) { struct snd_pcm_runtime *runtime = substream->runtime; AUDIO_DRIVER_HANDLE_t drv_handle = substream->runtime->private_data; char *buf_start = runtime->dma_area; int period_bytes = frames_to_bytes(runtime, runtime->period_size); char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos); int bytes_to_copy = frames_to_bytes(runtime, count); int not_copied = copy_from_user(hwbuf, buf, bytes_to_copy); char *new_hwbuf = hwbuf + (bytes_to_copy - not_copied); #if defined(DYNAMIC_DMA_PLAYBACK) BRCM_AUDIO_Param_BufferReady_t param; long ret; int avail, wait, once = 0; int stream_id = 0; int dmaSize = 0; int numBlocks = 0; #else int periods_copied; #endif unsigned long flag; if (not_copied) { aError("%s: why didn't copy all the bytes?" " not_copied = %d, to_copy = %d\n", __func__, not_copied, bytes_to_copy); aTrace(LOG_ALSA_INTERFACE, "%s: stream = %d," " buf_start = %p, hwbuf = %p, " "new_hwbuf = %p,period_bytes = %d," " bytes_to_copy = %d, not_copied = %d\n", __func__, substream->number, buf_start, hwbuf, new_hwbuf, period_bytes, bytes_to_copy, not_copied); } #if defined(DYNAMIC_DMA_PLAYBACK) stream_id = StreamIdOfDriver(drv_handle); BUG_ON(stream_id < CSL_CAPH_STREAM_NONE || stream_id >= CSL_CAPH_STREAM_TOTAL); dmaSize = csl_audio_render_get_dma_size(stream_id); numBlocks = csl_audio_render_get_num_blocks(stream_id); param.drv_handle = drv_handle; param.stream = stream_id; param.size = bytes_to_copy; param.offset = frames_to_bytes(runtime, runtime->control->appl_ptr) + bytes_to_copy; /*non-blocking cases: dyndma with big dma, aplay, legacy audio hal etc*/ if (numBlocks != 8 || dmaSize > period_bytes || bytes_to_copy != DYNDMA_COPY_SIZE) { spin_lock_irqsave(©_lock, flag); avail = runtime->control->appl_ptr - runtime->status->hw_ptr; if (avail < 0) avail += runtime->buffer_size; avail = frames_to_bytes(runtime, avail); /*aTrace(LOG_ALSA_INTERFACE, "%s size %d, avail 0x%x dmaSize " "0x%x nBlocks %d read %x, write %x offset %x\n", __func__, bytes_to_copy, avail, dmaSize, numBlocks, (int)runtime->status->hw_ptr, (int)runtime->control->appl_ptr, param.offset);*/ csl_audio_render_buffer_ready(stream_id, param.size, param.offset); spin_unlock_irqrestore(©_lock, flag); return 0; } /*dyndma: when small dma is active, state is running, and data level is high, wait till it goes low. At least go thru the loop once.*/ do { spin_lock_irqsave(©_lock, flag); avail = runtime->control->appl_ptr - runtime->status->hw_ptr; if (avail < 0) avail += runtime->buffer_size; avail = frames_to_bytes(runtime, avail); wait = (avail > 2*period_bytes && runtime->status->state == SNDRV_PCM_STATE_RUNNING); /*aTrace(LOG_ALSA_INTERFACE, "%s size %d, avail 0x%x dmaSize " "0x%x nBlocks %d wait %d read %x, write %x\n", __func__, bytes_to_copy, avail, dmaSize, numBlocks, wait, (int)runtime->status->hw_ptr, (int)runtime->control->appl_ptr); */ if (once == 0) { once = 1; } else if (wait == 0) { spin_unlock_irqrestore(©_lock, flag); break; } /*data in the buffer had been counted by render. just tell render to set SW RDY*/ csl_audio_render_buffer_ready(stream_id, param.size, param.offset); if (wait) { spin_unlock_irqrestore(©_lock, flag); if (stream_id != 0) { init_completion(&completeDynDma[stream_id]); ret = wait_for_completion_timeout( &completeDynDma[stream_id], msecs_to_jiffies(3000)); if (ret == 0) { aError("%s complete timeout" "substream %d" "stream_id %d\n", __func__, substream->number, stream_id); wait = 0; } } else { /* if stream_id is 0, then copy request has come before playback started, don't wait in that case. */ wait = 0; } } else { spin_unlock_irqrestore(©_lock, flag); } param.size = 0; } while (wait); #else /** * Set DMA engine ready bit according to pos and count */ periods_copied = bytes_to_copy/period_bytes; while (periods_copied--) { BRCM_AUDIO_Param_BufferReady_t param_bufferready; param_bufferready.drv_handle = drv_handle; param_bufferready.stream = substream->number; param_bufferready.size = 0; param_bufferready.offset = 0; /*aTrace(LOG_ALSA_INTERFACE, "%s: stream = %d, " "ACTION_AUD_BufferReady\n", __func__, param_bufferready.stream);*/ AUDIO_Ctrl_Trigger(ACTION_AUD_BufferReady, ¶m_bufferready, NULL, 0); } #endif return 0; }
static long voip_ioctl(struct file *hw, unsigned int cmd, unsigned long arg) { bcm_caph_hwdep_voip_t *pvoip; voipdev *pvoipchrdevpvtdata; long ret = 0; Boolean enable = FALSE; Int32 size = 0; int data; voip_codec_type_data_t val; static UserCtrl_data_t *dataptr; brcm_alsa_chip_t *pchip = NULL; struct treq_sysparm_t *eq; struct snd_card *pcard = NULL; int rc; pvoipchrdevpvtdata = (voipdev *)hw->private_data; pvoip = (bcm_caph_hwdep_voip_t *)pvoipchrdevpvtdata->pvoip; pcard = (struct snd_card *)pvoipchrdevpvtdata->card; pchip = (brcm_alsa_chip_t *)pcard->private_data; aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH hwdep_ioctl cmd=%08X\n", cmd); switch (cmd) { case VoIP_Ioctl_GetVersion: /* ret = put_user(BrcmAACEncVersion, (int __user *)arg); */ break; case VoIP_Ioctl_Start: get_user(data, (int __user *)arg); aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start type=%d (2==UL)" "voipinstcnt=%u\n", data, voipinstcnt); rc = down_interruptible(&sVoipAction); if (rc) return rc; aTrace(LOG_ALSA_INTERFACE,"VoIP_Ioctl_Start: acquired sVoipAction\n"); if (voipinstcnt == 0) { /* start VoIP only once */ BRCM_AUDIO_Param_RateChange_t param_rate_change; BRCM_AUDIO_Param_Open_t param_open; BRCM_AUDIO_Param_Prepare_t parm_prepare; BRCM_AUDIO_Param_Start_t param_start; voipinstcnt++; aTrace(LOG_ALSA_INTERFACE,"voipinstcnt=%d\n", voipinstcnt); #if 0 hw->private_data = kzalloc(sizeof(bcm_caph_hwdep_voip_t), GFP_KERNEL); CAPH_ASSERT(hw->private_data); pvoip = (bcm_caph_hwdep_voip_t *) hw->private_data; #endif pvoipchrdevpvtdata->pvoip = kzalloc(sizeof(bcm_caph_hwdep_voip_t), GFP_KERNEL); pvoip = pvoipchrdevpvtdata->pvoip; CAPH_ASSERT(pvoip); init_waitqueue_head(&pvoip->sleep); pvoip->buffer_handle = (audio_voip_driver_t *) kzalloc(sizeof(audio_voip_driver_t), GFP_KERNEL); aTrace(LOG_ALSA_INTERFACE,"pvoip->buffer_handle=0x%x",pvoip->buffer_handle); if (pvoip->buffer_handle) memset((u8 *) pvoip->buffer_handle, 0, sizeof(audio_voip_driver_t)); else { pvoip->buffer_handle = NULL; voipinstcnt--; up(&sVoipAction); aError("voip_ioctl failed with ENOMEM 1"); return -ENOMEM; } /*ul data*/ if (pchip->voip_data.codec_type_ul == VoIP_Codec_None) { if (pchip->voip_data.codec_type_dl != VoIP_Codec_None) pchip->voip_data.codec_type_ul = pchip->voip_data.codec_type_dl; else pchip->voip_data.codec_type_ul = VoIP_Codec_PCM_16K; // by default aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start: VoIPCmd forced UL codec [0x%x]\n", pchip->voip_data.codec_type_ul); } pvoip->codec_type_ul = pchip->voip_data.codec_type_ul; pvoip->frame_size_ul = svoipframelen[pvoip-> codec_type_ul - 1]; pvoip->buffer_size_ul = pvoip->frame_size_ul * VOIP_FRAMES_IN_BUFFER; pvoip->buffer_handle->voip_data_ul_buf_ptr = kzalloc(pvoip->buffer_size_ul, GFP_KERNEL); aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start: voip_data_ul_buf_ptr=0x%x," "buffer_size_ul=%d\n", pvoip->buffer_handle->voip_data_ul_buf_ptr, pvoip->buffer_size_ul); if (pvoip->buffer_handle->voip_data_ul_buf_ptr) memset(pvoip->buffer_handle-> voip_data_ul_buf_ptr, 0, pvoip->buffer_size_ul); else { if (pvoip->buffer_handle-> voip_data_dl_buf_ptr) { kfree(pvoip->buffer_handle-> voip_data_dl_buf_ptr); pvoip->buffer_handle-> voip_data_dl_buf_ptr = NULL; } pvoip->buffer_handle->voip_data_ul_buf_ptr = NULL; kfree(pvoip->buffer_handle); pvoip->buffer_handle = NULL; voipinstcnt--; up(&sVoipAction); aError("voip_ioctl failed with ENOMEM 2"); return -ENOMEM; } /*dl data*/ if (pchip->voip_data.codec_type_dl == VoIP_Codec_None) { if (pchip->voip_data.codec_type_ul != VoIP_Codec_None) pchip->voip_data.codec_type_dl = pchip->voip_data.codec_type_ul; else pchip->voip_data.codec_type_dl = VoIP_Codec_PCM_16K; // by default aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start: VoIPCmd forced DL codec [0x%x]\n", pchip->voip_data.codec_type_dl); } pvoip->codec_type_dl = pchip->voip_data.codec_type_dl; pvoip->frame_size_dl = svoipframelen[pvoip-> codec_type_dl - 1]; pvoip->buffer_size_dl = pvoip->frame_size_dl * VOIP_FRAMES_IN_BUFFER; pvoip->buffer_handle->voip_data_dl_buf_ptr = kzalloc(pvoip->buffer_size_dl, GFP_KERNEL); if (pvoip->buffer_handle->voip_data_dl_buf_ptr) { memset(pvoip->buffer_handle-> voip_data_dl_buf_ptr, 0, pvoip->buffer_size_dl); } else { if (pvoip->buffer_handle-> voip_data_ul_buf_ptr) { kfree(pvoip->buffer_handle-> voip_data_ul_buf_ptr); pvoip->buffer_handle-> voip_data_ul_buf_ptr = NULL; } pvoip->buffer_handle->voip_data_dl_buf_ptr = NULL; kfree(pvoip->buffer_handle); pvoip->buffer_handle = NULL; voipinstcnt--; up(&sVoipAction); aError("voip_ioctl failed with ENOMEM 3"); return -ENOMEM; } param_open.drv_handle = NULL; param_open.drv_type = AUDIO_DRIVER_VOIP; AUDIO_Ctrl_Trigger(ACTION_AUD_OpenVoIP, ¶m_open, NULL, 1); pvoip->buffer_handle->drv_handle = param_open.drv_handle; if (!pvoip->buffer_handle->drv_handle) { kfree(pvoip->buffer_handle-> voip_data_dl_buf_ptr); pvoip->buffer_handle-> voip_data_dl_buf_ptr = NULL; kfree(pvoip->buffer_handle-> voip_data_ul_buf_ptr); pvoip->buffer_handle-> voip_data_ul_buf_ptr = NULL; kfree(pvoip->buffer_handle); pvoip->buffer_handle = NULL; voipinstcnt--; up(&sVoipAction); aError("voip_ioctl failed with ENOMEM 4"); return -ENOMEM; } /* set UL callback */ parm_prepare.drv_handle = pvoip->buffer_handle->drv_handle; parm_prepare.cbParams.voipULCallback = HWDEP_VOIP_DumpUL_CB; parm_prepare.cbParams.pPrivateData = (void *)pvoip; AUDIO_Ctrl_Trigger( ACTION_AUD_SET_VOIP_UL_CB, &parm_prepare, NULL, 0); /* set DL callback */ parm_prepare.drv_handle = pvoip->buffer_handle->drv_handle; parm_prepare.cbParams.voipDLCallback = HWDEP_VOIP_FillDL_CB; parm_prepare.cbParams.pPrivateData = (void *)pvoip; AUDIO_Ctrl_Trigger( ACTION_AUD_SET_VOIP_DL_CB, &parm_prepare, NULL, 0); /* VoIP is always 16K. No need to set the codec type here*/ if (isvolte) { if (((data == VoIP_UL) && ((pvoip->codec_type_ul == VoIP_Codec_PCM_16K) || (pvoip->codec_type_ul == VOIP_Codec_AMR_WB_7K))) || ((data == VoIP_DL) && ((pvoip->codec_type_dl == VoIP_Codec_PCM_16K) || (pvoip->codec_type_dl == VOIP_Codec_AMR_WB_7K)))) { /* VOIP_PCM_16K or VOIP_AMR_WB_MODE_7k */ param_rate_change.codecID = 0x0A; } else param_rate_change.codecID = 0x06; AUDIO_Ctrl_Trigger(ACTION_AUD_RateChange, ¶m_rate_change, NULL, 0); } param_start.drv_handle = pvoip->buffer_handle->drv_handle; param_start.data = (void *)&pchip->voip_data; AUDIO_Ctrl_Trigger(ACTION_AUD_StartVoIP, ¶m_start, NULL, 0); pvoip->writecount = VOIP_FRAMES_IN_BUFFER; pvoip->status = voip_hwdep_status_started; aTrace(LOG_ALSA_INTERFACE, "Status made to voip_hwdep_status_started"); } else { voipinstcnt++; /*Limit Voip instance to two*/ if (voipinstcnt > 2) voipinstcnt = 2; aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start -> just increment " "the count, voip already started voipinstcnt=%d\n", voipinstcnt); } if (pvoip != NULL) { if (data == VoIP_UL) pvoip->ulstarted = 1; else pvoip->dlstarted = 1; } up(&sVoipAction); aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Start END voipinstcnt=%d\n",voipinstcnt); break; case VoIP_Ioctl_Stop: get_user(data, (int __user *)arg); aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Stop type=%d (2==UL) " "voipinstcnt=%u\n", data, voipinstcnt); rc = down_interruptible(&sVoipAction); if (rc) return rc; aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Stop acquired sVoipAction"); if (data == VoIP_UL) pvoip->ulstarted = 0; else pvoip->dlstarted = 0; if (voipinstcnt >= 2) { voipinstcnt--; aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Stop--1--voipinstcnt=%d\n", voipinstcnt); } else if ((voipinstcnt < 2) || (pvoip->ulstarted == 0 && pvoip->dlstarted == 0)) { BRCM_AUDIO_Param_Stop_t param_stop; BRCM_AUDIO_Param_Close_t param_close; voipinstcnt = 0; aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_Stop--2--voipinstcnt=%d\n", voipinstcnt); if (pvoip->buffer_handle) param_stop.drv_handle = pvoip->buffer_handle->drv_handle; else param_stop.drv_handle = NULL; AUDIO_Ctrl_Trigger(ACTION_AUD_StopVoIP, ¶m_stop, NULL, 0); if (pvoip->buffer_handle) param_close.drv_handle = pvoip->buffer_handle->drv_handle; else param_close.drv_handle = NULL; AUDIO_Ctrl_Trigger(ACTION_AUD_CloseVoIP, ¶m_close, NULL, 1); if (pvoip->buffer_handle) { kfree(pvoip->buffer_handle->voip_data_dl_buf_ptr); pvoip->buffer_handle->voip_data_dl_buf_ptr = NULL; kfree(pvoip->buffer_handle->voip_data_ul_buf_ptr); pvoip->buffer_handle->voip_data_ul_buf_ptr = NULL; kfree(pvoip->buffer_handle); pvoip->buffer_handle = NULL; } pvoip->status = voip_hwdep_status_stopped; wake_up(&pvoip->sleep); } up(&sVoipAction); break; case VoIP_Ioctl_SetSource: aTrace(LOG_ALSA_INTERFACE , " Warning: VoIP_Ioctl_SetSource" "is depreciated , please" "use mixer control VC-SEL instead\n"); break; case VoIP_Ioctl_SetSink: aTrace(LOG_ALSA_INTERFACE , " Warning: VoIP_Ioctl_SetSink" "is depreciated, please" "use mixer control VC-SEL instead\n"); break; case VoIP_Ioctl_SetCodecType: aTrace(LOG_ALSA_INTERFACE, "VoIP_Ioctl_SetCodecType\n"); copy_from_user(&val, (int __user *)arg, sizeof(voip_codec_type_data_t)); if (val.ul_dl_type == VoIP_UL) { pchip->voip_data.codec_type_ul = val.codec_type; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_SetCodecType (UL) codec_type %ld\n", pchip->voip_data.codec_type_ul); /*pvoip = (bcm_caph_hwdep_voip_t *) hw->private_data;*/ if (!pvoip) break; pvoip->codec_type_ul = pchip->voip_data.codec_type_ul; } else { pchip->voip_data.codec_type_dl = val.codec_type; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_SetCodecType (DL) codec_type %ld\n", pchip->voip_data.codec_type_dl); /*pvoip = (bcm_caph_hwdep_voip_t *) hw->private_data;*/ if (!pvoip) break; pvoip->codec_type_dl = pchip->voip_data.codec_type_dl; } /*Check whether in a VoLTE call*/ /*If no, do nothing.*/ /*If yes, do the NB<->WB switching*/ if (isvolte) { BRCM_AUDIO_Param_RateChange_t param_rate_change; if (pvoip->ulstarted == 0 && pvoip->dlstarted == 0) break; if (!(pvoip->buffer_handle)) break; if (!(pvoip->buffer_handle->drv_handle)) break; AUDIO_DRIVER_Ctrl(pvoip->buffer_handle->drv_handle, AUDIO_DRIVER_SET_AMR, &pchip->voip_data); if (((val.ul_dl_type == VoIP_UL) && ((pvoip->codec_type_ul == VoIP_Codec_PCM_16K) || (pvoip->codec_type_ul == VOIP_Codec_AMR_WB_7K))) || ((val.ul_dl_type == VoIP_DL) && ((pvoip->codec_type_dl == VoIP_Codec_PCM_16K) || (pvoip->codec_type_dl == VOIP_Codec_AMR_WB_7K)))) /* VOIP_PCM_16K or VOIP_AMR_WB_MODE_7k */ param_rate_change.codecID = 0x0A; else param_rate_change.codecID = 0x06; AUDIO_Ctrl_Trigger(ACTION_AUD_RateChange, ¶m_rate_change, NULL, 0); } break; case VoIP_Ioctl_SetBitrate: get_user(data, (int __user *)arg); pchip->voip_data.bitrate_index = (u32) data; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_SetBitrate bitrate_index %ld,\n", pchip->voip_data.bitrate_index); /*pvoip = (bcm_caph_hwdep_voip_t *) hw->private_data;*/ if (!pvoip) break; if (isvolte) { if (pvoip->ulstarted == 0 && pvoip->dlstarted == 0) break; if (!(pvoip->buffer_handle)) break; if (!(pvoip->buffer_handle->drv_handle)) break; AUDIO_DRIVER_Ctrl(pvoip->buffer_handle->drv_handle, AUDIO_DRIVER_SET_AMR, &pchip->voip_data); } break; case VoIP_Ioctl_GetSource: { s32 *psel; psel = pchip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1] .iLineSelect; data = (int)psel[0]; put_user(data, (int __user *)arg); } break; case VoIP_Ioctl_GetSink: { s32 *psel; psel = pchip->streamCtl[CTL_STREAM_PANEL_VOICECALL - 1] .iLineSelect; data = (int)psel[1]; put_user(data, (int __user *)arg); } break; case VoIP_Ioctl_GetCodecType: aTrace(LOG_ALSA_INTERFACE, "voip_ioctl in VoIP_Ioctl_GetCodecType"); copy_from_user(&val, (int __user *)arg, sizeof(voip_codec_type_data_t)); if (val.ul_dl_type == VoIP_UL) val.codec_type = (int)pchip->voip_data.codec_type_ul; else val.codec_type = (int)pchip->voip_data.codec_type_dl; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_GetCodecType (UL:DL) codec_type %ld:%ld\n", pchip->voip_data.codec_type_ul, pchip->voip_data.codec_type_dl); copy_to_user((int __user *)arg, &val, sizeof(voip_codec_type_data_t)); break; case VoIP_Ioctl_GetBitrate: data = (int)pchip->voip_data.bitrate_index; put_user(data, (int __user *)arg); break; case VoIP_Ioctl_GetMode: { AudioMode_t mode = AUDCTRL_GetAudioMode(); put_user((int)mode, (int __user *)arg); aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_GetMode mode %d,\n", mode); } break; case VoIP_Ioctl_SetMode: aTrace(LOG_ALSA_INTERFACE , " Warning: VoIP_Ioctl_SetMode" "is depreciated, please " "use mixer control VC-SEL instead\n"); break; case VoIP_Ioctl_SetVoLTEDTX: get_user(data, (int __user *)arg); pchip->voip_data.isDTXEnabled = (u8) data; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_SetVoLTEDTX %d,\n", pchip->voip_data.isDTXEnabled); /*pvoip = (bcm_caph_hwdep_voip_t *) hw->private_data;*/ if (!pvoip) break; if (!(pvoip->buffer_handle)) break; if (!(pvoip->buffer_handle->drv_handle)) break; AUDIO_DRIVER_Ctrl(pvoip->buffer_handle->drv_handle, AUDIO_DRIVER_SET_DTX, &pchip->voip_data); break; case VoIP_Ioctl_SetVoLTEFlag: get_user(data, (int __user *)arg); pchip->voip_data.isVoLTE = (u8) data; aTrace(LOG_ALSA_INTERFACE, " VoIP_Ioctl_SetFlag isVoLTE %d,\n", pchip->voip_data.isVoLTE); isvolte = pchip->voip_data.isVoLTE; break; case VoIP_Ioctl_GetVoLTEFlag: data = (int)pchip->voip_data.isVoLTE; put_user(data, (int __user *)arg); break; case DSPCtrl_Ioctl_SPCtrl: if (dataptr == NULL) dataptr = kzalloc(sizeof(UserCtrl_data_t), GFP_KERNEL); else memset(dataptr, 0, sizeof(UserCtrl_data_t)); if (!dataptr) return -ENOMEM; ret = copy_from_user(dataptr, (int __user *)arg, sizeof(UserCtrl_data_t)); enable = (Boolean) dataptr->data[0]; size = dataptr->data[1]; ret = AUDDRV_User_CtrlDSP(AUDDRV_USER_SP_CTRL, enable, size, (void *)&(dataptr->data[2])); if (!enable) { kfree(dataptr); dataptr = NULL; } break; case DSPCtrl_Ioctl_SPSetVar: /* * Will move this part later after we separate the voip and * dspctrl connections. */ if (dataptr == NULL) dataptr = kzalloc(sizeof(UserCtrl_data_t), GFP_KERNEL); else memset(dataptr, 0, sizeof(UserCtrl_data_t)); if (!dataptr) return -ENOMEM; ret = copy_from_user(dataptr, (int __user *)arg, sizeof(UserCtrl_data_t)); size = dataptr->data[0]; ret = AUDDRV_User_CtrlDSP(AUDDRV_USER_SP_VAR, enable, size, (void *)&(dataptr->data[2])); break; case DSPCtrl_Ioctl_SPQuery: if (dataptr == NULL) dataptr = kzalloc(sizeof(UserCtrl_data_t), GFP_KERNEL); else memset(dataptr, 0, sizeof(UserCtrl_data_t)); if (!dataptr) return -ENOMEM; ret = AUDDRV_User_CtrlDSP(AUDDRV_USER_SP_QUERY, enable, size, (void *)dataptr); if (ret < 0) return ret; if (copy_to_user ((int __user *)arg, dataptr, sizeof(UserCtrl_data_t))) return -EFAULT; break; case DSPCtrl_Ioctl_EQCtrl: if (dataptr == NULL) dataptr = kzalloc(sizeof(UserCtrl_data_t), GFP_KERNEL); else memset(dataptr, 0, sizeof(UserCtrl_data_t)); if (!dataptr) return -ENOMEM; if (copy_from_user (dataptr, (int __user *)arg, sizeof(UserCtrl_data_t))) return -EFAULT; enable = (Boolean) dataptr->data[0]; ret = AUDDRV_User_CtrlDSP(AUDDRV_USER_EQ_CTRL, enable, size, (void *)&(dataptr->data[2])); if (!enable) { kfree(dataptr); dataptr = NULL; } break; case Ctrl_Ioctl_SWEQParm: aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH hwdep_ioctl Ctrl_Ioctl_SWEQParm"); eq = kzalloc(sizeof(*eq), GFP_KERNEL); if (eq == NULL) { aError("treq_sysparm_t mem alloc failed"); return -ENOMEM; } /* get the sysparm from driver SW EQ is only for music playback for now*/ if (copy_from_user(eq, (int __user *)arg, sizeof(struct treq_sysparm_t))) { if (eq != NULL) { kfree(eq); eq = NULL; } return -EFAULT; } ret = AUDDRV_Get_TrEqParm((void *)eq, sizeof(*eq), AUDIO_APP_MUSIC, (eq->data)[TREQ_DATA_SIZE-1]); if (!ret) { if (copy_to_user((void __user *)arg, eq, sizeof(*eq))) { if (eq != NULL) { kfree(eq); eq = NULL; } return -EFAULT; } } if (eq != NULL) { kfree(eq); eq = NULL; } break; default: ret = -ENOTTY; break; } return ret; }