Ejemplo n.º 1
0
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec)
{
	int err;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;

	pm_qos_update_request(&drv->rx_pm_qos_req,
			      msm_cpuidle_get_deep_idle_latency());

	/* Remove the vote for SMPS mode*/
	err = pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE);
	if (err != 0)
		MM_ERR("pmapp_smps_mode_vote error %d\n", err);

	/* Disable power amplifier */
	if (icodec->data->pamp_off)
		icodec->data->pamp_off();

	/* Disable ADIE */
	adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF);
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;

	afe_disable(AFE_HW_PATH_CODEC_RX);

	if (icodec->data->voltage_off)
		icodec->data->voltage_off();

	/* Disable LPA Sub system */
	lpa_cmd_enable_codec(drv->lpa, 0);
	lpa_put(drv->lpa);

	/* Disable LPA clocks */
	clk_disable_unprepare(drv->lpa_p_clk);
	clk_disable_unprepare(drv->lpa_codec_clk);
	clk_disable_unprepare(drv->lpa_core_clk);

	/* Disable MI2S RX master block */
	/* Disable MI2S RX bit clock */
	clk_disable_unprepare(drv->rx_sclk);
	clk_disable_unprepare(drv->rx_mclk);

	icodec->enabled = 0;

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;
}
Ejemplo n.º 2
0
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec)
{
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	int i, err;

	pm_qos_update_request(&drv->tx_pm_qos_req,
			      msm_cpuidle_get_deep_idle_latency());

	/* Remove the vote for SMPS mode*/
	err = pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE);
	if (err != 0)
		MM_ERR("pmapp_smps_mode_vote error %d\n", err);

	afe_disable(AFE_HW_PATH_CODEC_TX);

	/* Disable ADIE */
	adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF);
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;

	/* Disable MI2S TX master block */
	/* Disable MI2S TX bit clock */
	clk_disable_unprepare(drv->tx_sclk);
	clk_disable_unprepare(drv->tx_mclk);

	/* Disable mic bias */
	for (i = 0; i < icodec->data->pmctl_id_sz; i++) {
		pmic_hsed_enable(icodec->data->pmctl_id[i],
			 PM_HSED_ENABLE_OFF);
	}

	/* Reuse pamp_off for TX platform-specific setup  */
	if (icodec->data->pamp_off)
		icodec->data->pamp_off();

	icodec->enabled = 0;

	pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;
}
Ejemplo n.º 3
0
static void debugfs_afe_loopback(u32 loop)
{
	int trc;
	struct msm_afe_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	struct lpa_codec_config lpa_config;

	if (loop) {
		/* Vote for SMPS mode*/
		pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID,
				PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM);

		/* enable MI2S RX master block */
		/* enable MI2S RX bit clock */
		trc = clk_set_rate(drv->rx_mclk,
		SNDDEV_ICODEC_CLK_RATE(8000));
		if (IS_ERR_VALUE(trc))
			MM_ERR("failed to set clk rate\n");
		clk_enable(drv->rx_mclk);
		clk_enable(drv->rx_sclk);
		clk_enable(drv->lpa_p_clk);
		clk_enable(drv->lpa_codec_clk);
		clk_enable(drv->lpa_core_clk);
		/* Enable LPA sub system
		 */
		drv->lpa = lpa_get();
		if (!drv->lpa)
			MM_ERR("failed to enable lpa\n");
		lpa_config.sample_rate = 8000;
		lpa_config.sample_width = 16;
		lpa_config.output_interface = LPA_OUTPUT_INTF_WB_CODEC;
		lpa_config.num_channels = 1;
		lpa_cmd_codec_config(drv->lpa, &lpa_config);
		/* Set audio interconnect reg to LPA */
		audio_interct_codec(AUDIO_INTERCT_LPA);
		mi2s_set_codec_output_path(MI2S_CHAN_MONO_PACKED, WT_16_BIT);
		MM_INFO("configure ADIE RX path\n");
		/* Configure ADIE */
		adie_codec_open(&debug_rx_profile, &debugfs_rx_adie);
		adie_codec_setpath(debugfs_rx_adie, 8000, 256);
		lpa_cmd_enable_codec(drv->lpa, 1);

		/* Start AFE for RX */
		afe_config.sample_rate = 0x8;
		afe_config.channel_mode = 1;
		afe_config.volume = AFE_VOLUME_UNITY;
		MM_INFO("enable afe\n");
		trc = afe_enable(AFE_HW_PATH_CODEC_RX, &afe_config);
		if (IS_ERR_VALUE(trc))
			MM_ERR("fail to enable afe RX\n");
		adie_codec_proceed_stage(debugfs_rx_adie,
		ADIE_CODEC_DIGITAL_READY);
		adie_codec_proceed_stage(debugfs_rx_adie,
		ADIE_CODEC_DIGITAL_ANALOG_READY);

		/* Vote for PWM mode*/
		pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM);

		MM_INFO("Enable Handset Mic bias\n");
		pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_PWM_TCXO);

		/* enable MI2S TX master block */
		/* enable MI2S TX bit clock */
		clk_set_rate(drv->tx_mclk,
			SNDDEV_ICODEC_CLK_RATE(8000));
		clk_enable(drv->tx_mclk);
		clk_enable(drv->tx_sclk);
		/* Set MI2S */
		mi2s_set_codec_input_path(MI2S_CHAN_MONO_PACKED, WT_16_BIT);
		MM_INFO("configure ADIE TX path\n");
		/* Configure ADIE */
		adie_codec_open(&debug_tx_profile, &debugfs_tx_adie);
		adie_codec_setpath(debugfs_tx_adie, 8000, 256);
		adie_codec_proceed_stage(debugfs_tx_adie,
		ADIE_CODEC_DIGITAL_READY);
		adie_codec_proceed_stage(debugfs_tx_adie,
		ADIE_CODEC_DIGITAL_ANALOG_READY);
		/* Start AFE for TX */
		afe_config.sample_rate = 0x8;
		afe_config.channel_mode = 1;
		afe_config.volume = AFE_VOLUME_UNITY;
		trc = afe_enable(AFE_HW_PATH_CODEC_TX, &afe_config);
		if (IS_ERR_VALUE(trc))
			MM_ERR("failed to enable AFE TX\n");
		/* Set the volume level to non unity, to avoid
		   loopback effect */
		afe_device_volume_ctrl(AFE_HW_PATH_CODEC_RX, 0x0500);

		/* enable afe loopback */
		afe_loopback(1);
		MM_INFO("AFE loopback enabled\n");
	} else {
		/* disable afe loopback */
		afe_loopback(0);
		/* Remove the vote for SMPS mode*/
		pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE);

		/* Disable ADIE */
		adie_codec_proceed_stage(debugfs_rx_adie,
		ADIE_CODEC_DIGITAL_OFF);
		adie_codec_close(debugfs_rx_adie);
		/* Disable AFE for RX */
		afe_disable(AFE_HW_PATH_CODEC_RX);

		/* Disable LPA Sub system */
		lpa_cmd_enable_codec(drv->lpa, 0);
		lpa_put(drv->lpa);

		/* Disable LPA clocks */
		clk_disable(drv->lpa_p_clk);
		clk_disable(drv->lpa_codec_clk);
		clk_disable(drv->lpa_core_clk);

		/* Disable MI2S RX master block */
		/* Disable MI2S RX bit clock */
		clk_disable(drv->rx_sclk);
		clk_disable(drv->rx_mclk);

		pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE);

		/* Disable AFE for TX */
		afe_disable(AFE_HW_PATH_CODEC_TX);

		/* Disable ADIE */
		adie_codec_proceed_stage(debugfs_tx_adie,
		ADIE_CODEC_DIGITAL_OFF);
		adie_codec_close(debugfs_tx_adie);
		/* Disable MI2S TX master block */
		/* Disable MI2S TX bit clock */
		clk_disable(drv->tx_sclk);
		clk_disable(drv->tx_mclk);
		pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_OFF);
		MM_INFO("AFE loopback disabled\n");
	}
}
Ejemplo n.º 4
0
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec)
{
	int trc;
	int i, err;
	struct msm_afe_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;;

	wake_lock(&drv->tx_idlelock);

	/* Vote for PWM mode*/
	err = pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID,
			PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM);
	if (err != 0)
		MM_ERR("pmapp_smps_mode_vote error %d\n", err);

	/* Reuse pamp_on for TX platform-specific setup  */
	if (icodec->data->pamp_on)
		icodec->data->pamp_on();

	for (i = 0; i < icodec->data->pmctl_id_sz; i++) {
		pmic_hsed_enable(icodec->data->pmctl_id[i],
			 PM_HSED_ENABLE_PWM_TCXO);
	}

	/* enable MI2S TX master block */
	/* enable MI2S TX bit clock */
	trc = clk_set_rate(drv->tx_mclk,
		SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
	if (IS_ERR_VALUE(trc))
		goto error_invalid_freq;
	clk_enable(drv->tx_mclk);
	clk_enable(drv->tx_sclk);

	/* Set MI2S */
	mi2s_set_codec_input_path((icodec->data->channel_mode ==
				REAL_STEREO_CHANNEL_MODE ? MI2S_CHAN_STEREO :
				(icodec->data->channel_mode == 2 ?
				 MI2S_CHAN_STEREO : MI2S_CHAN_MONO_RAW)),
				WT_16_BIT);
	/* Configure ADIE */
	trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
	if (IS_ERR_VALUE(trc))
		goto error_adie;
	/* Enable ADIE */
	adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256);
	adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY);
	adie_codec_proceed_stage(icodec->adie_path,
	ADIE_CODEC_DIGITAL_ANALOG_READY);

	/* Start AFE */
	afe_config.sample_rate = icodec->sample_rate / 1000;
	afe_config.channel_mode = icodec->data->channel_mode;
	afe_config.volume = AFE_VOLUME_UNITY;
	trc = afe_enable(AFE_HW_PATH_CODEC_TX, &afe_config);
	if (IS_ERR_VALUE(trc))
		goto error_afe;


	icodec->enabled = 1;

	wake_unlock(&drv->tx_idlelock);
	return 0;

error_afe:
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;
error_adie:
	clk_disable(drv->tx_sclk);
	clk_disable(drv->tx_mclk);
error_invalid_freq:

	/* Disable mic bias */
	for (i = 0; i < icodec->data->pmctl_id_sz; i++) {
		pmic_hsed_enable(icodec->data->pmctl_id[i],
			 PM_HSED_ENABLE_OFF);
	}

	if (icodec->data->pamp_off)
		icodec->data->pamp_off();

	MM_ERR("encounter error\n");

	wake_unlock(&drv->tx_idlelock);
	return -ENODEV;
}
Ejemplo n.º 5
0
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec)
{
	int trc, err;
	int smps_mode = PMAPP_SMPS_MODE_VOTE_PWM;
	struct msm_afe_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	struct lpa_codec_config lpa_config;

	wake_lock(&drv->rx_idlelock);

	if ((icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_MONO) ||
		(icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_STEREO)) {
		/* Vote PMAPP_SMPS_MODE_VOTE_PFM for headset */
		smps_mode = PMAPP_SMPS_MODE_VOTE_PFM;
		MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PFM \n");
	} else
		MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PWM \n");

	/* Vote for SMPS mode*/
	err = pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID,
				PMAPP_VREG_S4, smps_mode);
	if (err != 0)
		MM_ERR("pmapp_smps_mode_vote error %d\n", err);

	/* enable MI2S RX master block */
	/* enable MI2S RX bit clock */
	trc = clk_set_rate(drv->rx_mclk,
		SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
	if (IS_ERR_VALUE(trc))
		goto error_invalid_freq;
	clk_enable(drv->rx_mclk);
	clk_enable(drv->rx_sclk);
	/* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */
	clk_enable(drv->lpa_p_clk);
	clk_enable(drv->lpa_codec_clk);
	clk_enable(drv->lpa_core_clk);

	/* Enable LPA sub system
	 */
	drv->lpa = lpa_get();
	if (!drv->lpa)
		goto error_lpa;
	lpa_config.sample_rate = icodec->sample_rate;
	lpa_config.sample_width = 16;
	lpa_config.output_interface = LPA_OUTPUT_INTF_WB_CODEC;
	lpa_config.num_channels = icodec->data->channel_mode;
	lpa_cmd_codec_config(drv->lpa, &lpa_config);

	/* Set audio interconnect reg to LPA */
	audio_interct_codec(AUDIO_INTERCT_LPA);

	/* Set MI2S */
	mi2s_set_codec_output_path((icodec->data->channel_mode == 2 ?
	MI2S_CHAN_STEREO : MI2S_CHAN_MONO_PACKED), WT_16_BIT);

	if (icodec->data->voltage_on)
		icodec->data->voltage_on();

	/* Configure ADIE */
	trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
	if (IS_ERR_VALUE(trc))
		goto error_adie;
	/* OSR default to 256, can be changed for power optimization
	 * If OSR is to be changed, need clock API for setting the divider
	 */
	adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256);
	/* Start AFE */
	afe_config.sample_rate = icodec->sample_rate / 1000;
	afe_config.channel_mode = icodec->data->channel_mode;
	afe_config.volume = AFE_VOLUME_UNITY;
	trc = afe_enable(AFE_HW_PATH_CODEC_RX, &afe_config);
	if (IS_ERR_VALUE(trc))
		goto error_afe;
	lpa_cmd_enable_codec(drv->lpa, 1);
	/* Enable ADIE */
	adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY);
	adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_ANALOG_READY);

	/* Enable power amplifier */
	if (icodec->data->pamp_on)
		icodec->data->pamp_on();

	icodec->enabled = 1;

	wake_unlock(&drv->rx_idlelock);
	return 0;

error_afe:
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;
error_adie:
	lpa_put(drv->lpa);
error_lpa:
	clk_disable(drv->lpa_p_clk);
	clk_disable(drv->lpa_codec_clk);
	clk_disable(drv->lpa_core_clk);
	clk_disable(drv->rx_sclk);
	clk_disable(drv->rx_mclk);
error_invalid_freq:

	MM_ERR("encounter error\n");

	wake_unlock(&drv->rx_idlelock);
	return -ENODEV;
}