Esempio n. 1
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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, &param, NULL, 0);
	}
#endif
	pos %= runtime->buffer_size;
	return pos;
}
Esempio n. 2
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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;
}
Esempio n. 3
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;
}
Esempio n. 4
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, &param_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;
}
Esempio n. 5
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, &param_close, NULL, 1);

	substream->runtime->private_data = NULL;
	chip->streamCtl[substream->number].pSubStream = NULL;

	return 0;
}
Esempio n. 6
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;
}
Esempio n. 7
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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, &param_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, &param_stop,
				   CtrlStopCB, (int)compl_ptr);

		if (ret == RESULT_ERROR) {
			complete(compl_ptr);
			chip->streamCtl[substream_number].pStopCompletion
			= NULL;
		}

		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Esempio n. 8
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, &param_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;

}
Esempio n. 9
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, &param_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, &param_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, &param_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, &param_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, &param_resume,
					   NULL, 0);

		}
		break;

	default:
		return -EINVAL;
	}

	return ret;
}
Esempio n. 10
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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, &param_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;
}
Esempio n. 11
0
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(&copy_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(&copy_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(&copy_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(&copy_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(&copy_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(&copy_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, &param_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,
				&param_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,
					&param_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,
				&param_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,
				&param_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,
				&param_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,
					&param_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;
}