Ejemplo n.º 1
0
static void audio_prevent_sleep(struct audio *audio)
{
	MM_DBG("\n"); /* Macro prints the file name and function */
	wake_lock(&audio->wakelock);
	pm_qos_update_request(&audio->pm_qos_req,
			      msm_cpuidle_get_deep_idle_latency());
}
Ejemplo n.º 2
0
static void pcm_in_prevent_sleep(struct pcm *audio)
{
	pr_debug("%s:\n", __func__);
	wake_lock(&audio->wakelock);
	pm_qos_update_request(&audio->pm_qos_req,
			      msm_cpuidle_get_deep_idle_latency());
}
bool wcd9xxx_lock_sleep(
	struct wcd9xxx_core_resource *wcd9xxx_res)
{
	enum wcd9xxx_pm_state os;

	mutex_lock(&wcd9xxx_res->pm_lock);
	if (wcd9xxx_res->wlock_holders++ == 0) {
		pr_debug("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&wcd9xxx_res->pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
	}
	mutex_unlock(&wcd9xxx_res->pm_lock);

	if (!wait_event_timeout(wcd9xxx_res->pm_wq,
				((os =  wcd9xxx_pm_cmpxchg(wcd9xxx_res,
						  WCD9XXX_PM_SLEEPABLE,
						  WCD9XXX_PM_AWAKE)) ==
							WCD9XXX_PM_SLEEPABLE ||
					(os == WCD9XXX_PM_AWAKE)),
				msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state,
			wcd9xxx_res->wlock_holders);
		wcd9xxx_unlock_sleep(wcd9xxx_res);
		return false;
	}
	wake_up_all(&wcd9xxx_res->pm_wq);
	return true;
}
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec)
{
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;

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

	if (drv->snddev_vreg)
		vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE);

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

	afe_close(icodec->data->copp_id);

	clk_disable_unprepare(drv->tx_bitclk);
	clk_disable_unprepare(drv->tx_osrclk);

	msm_snddev_tx_mclk_free();

	/* 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.º 5
0
static void spi_aic3254_prevent_sleep(void)
{
	struct ecodec_aic3254_state *codec_drv = &codec_clk;

	wake_lock(&codec_drv->wakelock);
	pm_qos_update_request(&codec_drv->pm_qos_req,
			msm_cpuidle_get_deep_idle_latency());
}
Ejemplo n.º 6
0
static int audio_mvs_start(struct audio_mvs_info_type *audio)
{
	int rc = 0;
	struct audio_mvs_acquire_msg acquire_msg;

	pr_info("%s:\n", __func__);

	/* Prevent sleep. */
	wake_lock(&audio->suspend_lock);
	pm_qos_update_request(&audio->pm_qos_req,
			      msm_cpuidle_get_deep_idle_latency());

	/* Acquire MVS. */
	memset(&acquire_msg, 0, sizeof(acquire_msg));
	acquire_msg.acquire_args.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
	acquire_msg.acquire_args.cb_func_id = cpu_to_be32(MVS_CB_FUNC_ID);

	msm_rpc_setup_req(&acquire_msg.rpc_hdr,
			  audio->rpc_prog,
			  audio->rpc_ver,
			  MVS_ACQUIRE_PROC);

	audio->rpc_status = RPC_STATUS_FAILURE;
	rc = msm_rpc_write(audio->rpc_endpt,
			   &acquire_msg,
			   sizeof(acquire_msg));

	if (rc >= 0) {
		pr_debug("%s: RPC write for acquire done\n", __func__);

		rc = wait_event_timeout(audio->wait,
			(audio->rpc_status != RPC_STATUS_FAILURE),
			1 * HZ);

		if (rc > 0) {

			rc = audio_mvs_setup(audio);

			if (rc == 0)
				audio->state = AUDIO_MVS_STARTED;

		} else {
			pr_err("%s: Wait event for acquire failed %d\n",
			       __func__, rc);

			rc = -EBUSY;
		}
	} else {
		pr_err("%s: RPC write for acquire failed %d\n", __func__, rc);

		rc = -EBUSY;
	}

	return rc;
}
bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 */
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_debug("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
		#ifdef VENDOR_EDIT
		//[email protected], 2015/03/19, Add for Qcom patch,
		//Headset sometime not detected when phone is sleep
		pm_stay_awake(&map.spmi[0]->dev);
		#endif /* VENDOR_EDIT */
	}
	mutex_unlock(&map.pm_lock);
	pr_debug("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);
	pr_debug("%s: map.pm_state = %d\n", __func__, map.pm_state);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state);
	return true;
}
Ejemplo n.º 8
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.º 9
0
bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by
	 * wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 */
	pr_info("%s, wlock_holders=%d\n", __func__, map.wlock_holders);
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_info("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
		pm_stay_awake(&map.spmi[0]->dev);
	}
	mutex_unlock(&map.pm_lock);
	pr_info("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);
	pr_info("%s: map.pm_state = %d\n", __func__, map.pm_state);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	pr_debug("%s: leaving pm_state = %d\n", __func__, map.pm_state);
	return true;
}
Ejemplo n.º 10
0
bool wcd9xxx_spmi_lock_sleep()
{
	/*
	 * wcd9xxx_spmi_{lock/unlock}_sleep will be called by wcd9xxx_spmi_irq_thread
	 * and its subroutines only motly.
	 * but btn0_lpress_fn is not wcd9xxx_spmi_irq_thread's subroutine and
	 * It can race with wcd9xxx_spmi_irq_thread.
	 * So need to embrace wlock_holders with mutex.
	 *
	 * If system didn't resume, we can simply return false so codec driver's
	 * IRQ handler can return without handling IRQ.
	 * As interrupt line is still active, codec will have another IRQ to
	 * retry shortly.
	 */
	mutex_lock(&map.pm_lock);
	if (map.wlock_holders++ == 0) {
		pr_debug("%s: holding wake lock\n", __func__);
		pm_qos_update_request(&map.pm_qos_req,
				      msm_cpuidle_get_deep_idle_latency());
	}
	mutex_unlock(&map.pm_lock);
	pr_debug("%s: wake lock counter %d\n", __func__,
			map.wlock_holders);

	if (!wait_event_timeout(map.pm_wq,
				((wcd9xxx_spmi_pm_cmpxchg(
					WCD9XXX_PM_SLEEPABLE,
					WCD9XXX_PM_AWAKE)) ==
					WCD9XXX_PM_SLEEPABLE ||
					(wcd9xxx_spmi_pm_cmpxchg(
						 WCD9XXX_PM_SLEEPABLE,
						 WCD9XXX_PM_AWAKE) ==
						 WCD9XXX_PM_AWAKE)),
					msecs_to_jiffies(
					WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
			__func__,
			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, map.pm_state,
			map.wlock_holders);
		wcd9xxx_spmi_unlock_sleep();
		return false;
	}
	wake_up_all(&map.pm_wq);
	return true;
}
Ejemplo n.º 11
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.º 12
0
int isdbt_power_on(unsigned long arg)
{
	int ret;

	ret = (*isdbtdrv_func->power_on)(arg);

#ifdef ISDBT_WAKE_LOCK_ENABLE
#if defined(CONFIG_MTV_QUALCOMM)
	pm_qos_update_request(&isdbt_pm_qos_req,
				  msm_cpuidle_get_deep_idle_latency());
#endif
	wake_lock(&isdbt_wlock);
#endif

	if (ret == 0)
		isdbt_pwr_on = true;
	else
		isdbt_pwr_on = false;

	DPRINTK("%s : ret(%d)\n", __func__, isdbt_pwr_on);
	return ret;
}
Ejemplo n.º 13
0
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec)
{
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	pr_info("%s\n", __func__);	//                      

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

	if (drv->snddev_vreg)
		vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE);

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

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

	afe_close(icodec->data->copp_id);

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

	clk_disable_unprepare(drv->rx_bitclk);
	clk_disable_unprepare(drv->rx_osrclk);

	msm_snddev_rx_mclk_free();

	icodec->enabled = 0;

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;
}
Ejemplo n.º 14
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;

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

	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_prepare_enable(drv->rx_mclk);
	clk_prepare_enable(drv->rx_sclk);
	/* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */
	clk_prepare_enable(drv->lpa_p_clk);
	clk_prepare_enable(drv->lpa_codec_clk);
	clk_prepare_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;

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;

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

	MM_ERR("encounter error\n");

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return -ENODEV;
}
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec)
{
	int trc;
	int afe_channel_mode;
	union afe_port_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;

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

	if (drv->snddev_vreg) {
		if (!strcmp(icodec->data->name, "headset_stereo_rx"))
			vreg_mode_vote(drv->snddev_vreg, 1,
					SNDDEV_LOW_POWER_MODE);
		else
			vreg_mode_vote(drv->snddev_vreg, 1,
					SNDDEV_HIGH_POWER_MODE);
	}
	msm_snddev_rx_mclk_request();

	drv->rx_osrclk = clk_get_sys(NULL, "i2s_spkr_osr_clk");
	if (IS_ERR(drv->rx_osrclk))
		pr_err("%s master clock Error\n", __func__);

	trc =  clk_set_rate(drv->rx_osrclk,
			SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
	if (IS_ERR_VALUE(trc)) {
		pr_err("ERROR setting m clock1\n");
		goto error_invalid_freq;
	}

	clk_prepare_enable(drv->rx_osrclk);
	drv->rx_bitclk = clk_get_sys(NULL, "i2s_spkr_bit_clk");
	if (IS_ERR(drv->rx_bitclk))
		pr_err("%s clock Error\n", __func__);

	/* Master clock = Sample Rate * OSR rate bit clock
	 * OSR Rate bit clock = bit/sample * channel master
	 * clock / bit clock = divider value = 8
	 */
	if (msm_codec_i2s_slave_mode) {
		pr_info("%s: configuring bit clock for slave mode\n",
				__func__);
		trc =  clk_set_rate(drv->rx_bitclk, 0);
	} else
		trc =  clk_set_rate(drv->rx_bitclk, 8);

	if (IS_ERR_VALUE(trc)) {
		pr_err("ERROR setting m clock1\n");
		goto error_adie;
	}
	clk_prepare_enable(drv->rx_bitclk);

	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))
		pr_err("%s: adie codec open failed\n", __func__);
	else
		adie_codec_setpath(icodec->adie_path,
					icodec->sample_rate, 256);
	/* OSR default to 256, can be changed for power optimization
	 * If OSR is to be changed, need clock API for setting the divider
	 */

	switch (icodec->data->channel_mode) {
	case 2:
		afe_channel_mode = MSM_AFE_STEREO;
		break;
	case 1:
	default:
		afe_channel_mode = MSM_AFE_MONO;
		break;
	}
	afe_config.mi2s.channel = afe_channel_mode;
	afe_config.mi2s.bitwidth = 16;
	afe_config.mi2s.line = 1;
	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;
	if (msm_codec_i2s_slave_mode)
		afe_config.mi2s.ws = 0;
	else
		afe_config.mi2s.ws = 1;

	trc = afe_open(icodec->data->copp_id, &afe_config, icodec->sample_rate);

	if (trc < 0)
		pr_err("%s: afe open failed, trc = %d\n", __func__, trc);

	/* Enable ADIE */
	if (icodec->adie_path) {
		adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_READY);
		adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_ANALOG_READY);
	}

	if (msm_codec_i2s_slave_mode)
		adie_codec_set_master_mode(icodec->adie_path, 1);
	else
		adie_codec_set_master_mode(icodec->adie_path, 0);

	/* Enable power amplifier */
	if (icodec->data->pamp_on) {
		if (icodec->data->pamp_on()) {
			pr_err("%s: Error turning on rx power\n", __func__);
			goto error_pamp;
		}
	}

	icodec->enabled = 1;

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;

error_pamp:
error_adie:
	clk_disable_unprepare(drv->rx_osrclk);
error_invalid_freq:

	pr_err("%s: encounter error\n", __func__);

	pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return -ENODEV;
}
Ejemplo n.º 16
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;;

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

	/* 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],
#if defined(CONFIG_MACH_KYLE) || defined(CONFIG_MACH_ROY)
			 PM_HSED_ENABLE_ALWAYS);
#else
			 PM_HSED_ENABLE_PWM_TCXO);
#endif
	}

	/* 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_prepare_enable(drv->tx_mclk);
	clk_prepare_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;

	pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;

error_afe:
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;
error_adie:
	clk_disable_unprepare(drv->tx_sclk);
	clk_disable_unprepare(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");

	pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return -ENODEV;
}
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec)
{
	int trc;
	int afe_channel_mode;
	union afe_port_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;;

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

	if (drv->snddev_vreg)
		vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_HIGH_POWER_MODE);

	/* Reuse pamp_on for TX platform-specific setup  */
	if (icodec->data->pamp_on) {
		if (icodec->data->pamp_on()) {
			pr_err("%s: Error turning on tx power\n", __func__);
			goto error_pamp;
		}
	}

	msm_snddev_tx_mclk_request();

	drv->tx_osrclk = clk_get_sys(NULL, "i2s_mic_osr_clk");
	if (IS_ERR(drv->tx_osrclk))
		pr_err("%s master clock Error\n", __func__);

	trc =  clk_set_rate(drv->tx_osrclk,
			SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
	if (IS_ERR_VALUE(trc)) {
		pr_err("ERROR setting m clock1\n");
		goto error_invalid_freq;
	}

	clk_prepare_enable(drv->tx_osrclk);
	drv->tx_bitclk = clk_get_sys(NULL, "i2s_mic_bit_clk");
	if (IS_ERR(drv->tx_bitclk))
		pr_err("%s clock Error\n", __func__);

	/* Master clock = Sample Rate * OSR rate bit clock
	 * OSR Rate bit clock = bit/sample * channel master
	 * clock / bit clock = divider value = 8
	 */
	if (msm_codec_i2s_slave_mode) {
		pr_info("%s: configuring bit clock for slave mode\n",
				__func__);
		trc =  clk_set_rate(drv->tx_bitclk, 0);
	} else
		trc =  clk_set_rate(drv->tx_bitclk, 8);

	clk_prepare_enable(drv->tx_bitclk);

	/* Enable ADIE */
	trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
	if (IS_ERR_VALUE(trc))
		pr_err("%s: adie codec open failed\n", __func__);
	else
		adie_codec_setpath(icodec->adie_path,
					icodec->sample_rate, 256);

	switch (icodec->data->channel_mode) {
	case 2:
		afe_channel_mode = MSM_AFE_STEREO;
		break;
	case 1:
	default:
		afe_channel_mode = MSM_AFE_MONO;
		break;
	}
	afe_config.mi2s.channel = afe_channel_mode;
	afe_config.mi2s.bitwidth = 16;
	afe_config.mi2s.line = 1;
	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;
	if (msm_codec_i2s_slave_mode)
		afe_config.mi2s.ws = 0;
	else
		afe_config.mi2s.ws = 1;

	trc = afe_open(icodec->data->copp_id, &afe_config, icodec->sample_rate);

	if (icodec->adie_path) {
		adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_READY);
		adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_ANALOG_READY);
	}

	if (msm_codec_i2s_slave_mode)
		adie_codec_set_master_mode(icodec->adie_path, 1);
	else
		adie_codec_set_master_mode(icodec->adie_path, 0);

	icodec->enabled = 1;

	pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return 0;

error_invalid_freq:

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

	pr_err("%s: encounter error\n", __func__);
error_pamp:
	pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE);
	return -ENODEV;
}