/*
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;
}
Exemple #2
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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;
}
Exemple #4
0
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;
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  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;
}