static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
		dev_get_drvdata(dai->dev);
	int rc;

	/* If AFE port is still up, close it */
	if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
		rc = afe_close(MI2S_RX); /* can block */
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close MI2S_RX port\n");
		clear_bit(STATUS_PORT_STARTED,
			  mi2s_dai_data->rx_dai.status_mask);
	}
	if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->tx_dai.status_mask)) {
		rc = afe_close(MI2S_TX); /* can block */
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close MI2S_TX port\n");
		clear_bit(STATUS_PORT_STARTED,
			  mi2s_dai_data->tx_dai.status_mask);
	}
	kfree(mi2s_dai_data);
	snd_soc_unregister_dai(dai->dev);

	return 0;
}
static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_dai_data *dai_data;
	int rc;

	dai_data = dev_get_drvdata(dai->dev);

	/* If AFE port is still up, close it */
	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_close(dai->id); /* can block */
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");
		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);

		rc = afe_close(PCM_TX);
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AUX PCM TX port\n");
	}


	kfree(dai_data);
	snd_soc_unregister_dai(dai->dev);

	return 0;
}
static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
	int rc = 0;

	rc = adm_close(dai->id);
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close ADM COPP\n");

	pr_debug("%s: dai->id = %d", __func__, dai->id);

	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		clk_disable(pcm_clk);
		rc = afe_close(dai->id); /* can block */
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");
		pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
			*dai_data->status_mask);
		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);

		rc = afe_close(PCM_TX);
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AUX PCM TX port\n");
	}
}
int snddev_ecodec_close(struct msm_snddev_info *dev_info)
{
	struct snddev_ecodec_drv_state *drv = &snddev_ecodec_drv;

	pr_debug("%s: closing %s\n", __func__, dev_info->name);

	mutex_lock(&drv->dev_lock);

	if (!dev_info->opened) {
		pr_err("%s: ERROR: %s is not opened\n", __func__,
				dev_info->name);
		mutex_unlock(&drv->dev_lock);
		return -EPERM;
	}

	drv->ref_cnt--;

	if (drv->ref_cnt == 0) {

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

		clk_disable_unprepare(drv->ecodec_clk);
		aux_pcm_gpios_free();

		afe_close(PCM_RX);
		afe_close(PCM_TX);
	}

	mutex_unlock(&drv->dev_lock);

	return 0;
}
示例#5
0
int snddev_ecodec_close(struct msm_snddev_info *dev_info)
{
	struct snddev_ecodec_drv_state *drv = &snddev_ecodec_drv;
#ifdef CONFIG_PANTECH_AUDIO_PRESTO_AUDIENCE2020 // jmlee	
	//int i;
       struct snddev_ecodec_state *ecodec;
#endif

	pr_debug("%s: closing %s\n", __func__, dev_info->name);

	mutex_lock(&drv->dev_lock);

	if (!dev_info->opened) {
		pr_err("%s: ERROR: %s is not opened\n", __func__,
				dev_info->name);
		mutex_unlock(&drv->dev_lock);
		return -EPERM;
	}

#ifdef CONFIG_PANTECH_AUDIO_PRESTO_AUDIENCE2020 // jmlee	
	/* audience disable */
       ecodec = dev_info->private_data;
	if (ecodec->data->pamp_off && (ecodec_audience_enable))
	{
		ecodec->data->pamp_off();
              ecodec_audience_enable = 0;

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

	drv->ref_cnt--;

	if (drv->ref_cnt == 0) {

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

		clk_disable(drv->ecodec_clk);
		aux_pcm_gpios_free();

		afe_close(PCM_RX);
		afe_close(PCM_TX);
	}

	mutex_unlock(&drv->dev_lock);

	return 0;
}
static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_dai_data *dai_data;
	int rc;

	dai_data = dev_get_drvdata(dai->dev);

	mutex_lock(&aux_pcm_mutex);

	if (aux_pcm_count == 0) {
		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
				" up and return\n", __func__, dai->id);
		goto done;
	}

	aux_pcm_count--;

	if (aux_pcm_count > 0) {
		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
			__func__, dai->id, aux_pcm_count);
		goto done;
	} else if (aux_pcm_count < 0) {
		dev_err(dai->dev, "%s(): ERROR: dai->id %d"
			" aux_pcm_count = %d < 0\n",
			__func__, dai->id, aux_pcm_count);
		goto done;
	}

	dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
			"closing afe\n",
		__func__, dai->id, aux_pcm_count);

	rc = afe_close(PCM_RX); /* can block */
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");

	rc = afe_close(PCM_TX);
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");

done:
	kfree(dai_data);
	snd_soc_unregister_dai(dai->dev);

	mutex_unlock(&aux_pcm_mutex);

	return 0;
}
static int snddev_hdmi_close(struct msm_snddev_info *dev_info)
{
    if (!dev_info) {
        pr_aud_err("msm_snddev_info is null\n");
        return -EINVAL;
    }

    if (!dev_info->opened) {
        pr_aud_err("calling close device with out opening the"
                   " device\n");
        return -EPERM;
    }
    mutex_lock(&snddev_hdmi_lock);

    if (!snddev_hdmi_active) {
        pr_aud_err("HDMI snddev not active\n");
        mutex_unlock(&snddev_hdmi_lock);
        return -EPERM;
    }
    snddev_hdmi_active = 0;

    afe_close(HDMI_RX);

    pr_debug("%s closed\n", dev_info->name);
    mutex_unlock(&snddev_hdmi_lock);

    return 0;
}
static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
				     struct snd_soc_dai *dai)
{
	struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
		dev_get_drvdata(dai->dev);
	struct msm_dai_q6_dai_data *dai_data =
		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
		&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
	u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
		MI2S_RX : MI2S_TX);
	int rc = 0;

	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_close(port_id);
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");
		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
	}

	if (!test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) &&
	    !test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
		mi2s_dai_data->rate_constraint.list = NULL;
		mi2s_dai_data->bitwidth_constraint.list = NULL;
	}

}
示例#9
0
static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
	int rc = 0;

	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		switch (dai->id) {
		case VOICE_PLAYBACK_TX:
		case VOICE_RECORD_TX:
		case VOICE_RECORD_RX:
			pr_debug("%s, stop pseudo port:%d\n",
						__func__,  dai->id);
			rc = afe_stop_pseudo_port(dai->id);
			break;
		default:
			rc = afe_close(dai->id); /* can block */
			break;
		}
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");
		pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
			*dai_data->status_mask);
		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
	}
}
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;
}
static int pcm_in_release(struct inode *inode, struct file *file)
{
	int rc = 0;
	struct pcm *pcm = file->private_data;

	pr_info("[AUD][%s:%s] release session id[%d]\n", __MM_FILE__,
		__func__, pcm->ac->session);
	mutex_lock(&pcm->lock);


	/* remove this session from topology list */
	auddev_cfg_tx_copp_topology(pcm->ac->session,
				DEFAULT_COPP_TOPOLOGY);

	rc = pcm_in_disable(pcm);
	hrtimer_cancel(&pcm->hrt);
	rc = afe_cmd_memory_unmap(pcm->dma_addr);
	if (rc < 0)
		pr_err("AFE memory unmap failed\n");
	rc =  afe_unregister_get_events(RT_PROXY_DAI_001_TX);
	if (rc < 0)
		pr_err("AFE unregister for events failed\n");

	afe_close(RT_PROXY_DAI_001_TX);
	pr_debug("release all buffer\n");
	q6asm_audio_client_buf_free_contiguous(OUT,
				pcm->ac);
	msm_clear_session_id(pcm->ac->session);
	q6asm_audio_client_free(pcm->ac);
	mutex_unlock(&pcm->lock);
	mutex_destroy(&pcm->lock);
	mutex_destroy(&pcm->read_lock);
	kfree(pcm);
	return rc;
}
示例#12
0
static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_dai_data *dai_data;
	int rc;

	dai_data = dev_get_drvdata(dai->dev);

	/* If AFE port is still up, close it */
	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		switch (dai->id) {
		case VOICE_PLAYBACK_TX:
		case VOICE_RECORD_TX:
		case VOICE_RECORD_RX:
			pr_debug("%s, stop pseudo port:%d\n",
				 __func__,  dai->id);
			rc = afe_stop_pseudo_port(dai->id);
			break;
		default:
			rc = afe_close(dai->id); /* can block */
		}
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");
		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
	}
	kfree(dai_data);
	snd_soc_unregister_dai(dai->dev);

	return 0;
}
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec)
{
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;

	wake_lock(&drv->tx_idlelock);

	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(drv->tx_bitclk);
	clk_disable(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;

	wake_unlock(&drv->tx_idlelock);
	return 0;
}
示例#14
0
static int snddev_mi2s_close(struct msm_snddev_info *dev_info)
{

	struct snddev_mi2s_drv_state *mi2s_drv = &snddev_mi2s_drv;
	struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;

	if (!dev_info) {
		pr_err("%s:  msm_snddev_info is null\n", __func__);
		return -EINVAL;
	}

	if (!dev_info->opened) {
		pr_err(" %s: calling close device with out opening the"
		       " device\n", __func__);
		return -EIO;
	}
	afe_close(snddev_mi2s_data->copp_id);
	clk_disable_unprepare(mi2s_drv->tx_bitclk);
	clk_disable_unprepare(mi2s_drv->tx_osrclk);

	mi2s_gpios_free();

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

	return 0;
}
示例#15
0
static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	int rc = 0;

	mutex_lock(&aux_pcm_mutex);

	if (aux_pcm_count == 0) {
		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just return\n",
				__func__, dai->id);
		mutex_unlock(&aux_pcm_mutex);
		return;
	}

	aux_pcm_count--;

	if (aux_pcm_count > 0) {
		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
			__func__, dai->id, aux_pcm_count);
		mutex_unlock(&aux_pcm_mutex);
		return;
	} else if (aux_pcm_count < 0) {
		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
			__func__, dai->id, aux_pcm_count);
		aux_pcm_count = 0;
		mutex_unlock(&aux_pcm_mutex);
		return;
	}

	pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
			dai->id, aux_pcm_count);

	rc = afe_close(PCM_RX); /* can block */
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close PCM_RX  AFE port\n");

	rc = afe_close(PCM_TX);
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close AUX PCM TX port\n");

	clk_disable_unprepare(pcm_branch_clk);
	clk_disable_unprepare(pcm_oe_branch_clk);

	mutex_unlock(&aux_pcm_mutex);
}
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec)
{
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	struct snddev_icodec_data *data = icodec->data;

	wake_lock(&drv->rx_idlelock);

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

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

	if (support_aic3254) {
		/* Restore default id for A3254 */
		if (data->aic3254_id != data->default_aic3254_id)
			data->aic3254_id = data->default_aic3254_id;
		/* Disable External Codec A3254 */
		if (aic3254_ops->aic3254_set_mode)
			aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX, DOWNLINK_OFF);
	}
	if (support_adie) {
		/* 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_on)
		icodec->data->voltage_on(0);

	clk_disable(drv->rx_bitclk);

	if (support_aic3254_use_mclk)
		snddev_icodec_rxclk_enable(icodec, 0);
	else
		clk_disable(drv->rx_osrclk);

	msm_snddev_rx_mclk_free();

	icodec->enabled = 0;

	wake_unlock(&drv->rx_idlelock);
	return 0;
}
示例#17
0
static int snddev_hdmi_close(struct msm_snddev_info *dev_info)
{

	struct snddev_hdmi_data *snddev_hdmi_data;

	if (!dev_info) {
		pr_err("msm_snddev_info is null\n");
		return -EINVAL;
	}

	snddev_hdmi_data = dev_info->private_data;

	if (!dev_info->opened) {
		pr_err("calling close device with out opening the"
		       " device\n");
		return -EPERM;
	}
	mutex_lock(&snddev_hdmi_lock);

	if (!snddev_hdmi_active) {
		pr_err("HDMI snddev not active\n");
		mutex_unlock(&snddev_hdmi_lock);
		return -EPERM;
	}
	snddev_hdmi_active = 0;

	if (snddev_hdmi_data->on_apps) {
		pr_debug("%s open done\n", dev_info->name);

		mutex_unlock(&snddev_hdmi_lock);
		return 0;
	}


	afe_close(HDMI_RX);

	pr_debug("%s closed\n", dev_info->name);
	mutex_unlock(&snddev_hdmi_lock);

	return 0;
}
static int msm_dai_q6_hdmi_dai_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_hdmi_dai_data *dai_data;
	int rc;

	dai_data = dev_get_drvdata(dai->dev);

	
	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_close(dai->id); 

		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");

		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
	}
	kfree(dai_data);
	snd_soc_unregister_dai(dai->dev);

	return 0;
}
示例#19
0
static void msm_dai_q6_hdmi_shutdown(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
	int rc = 0;

	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		pr_info("%s:  afe port not started. dai_data->status_mask"
			" = %ld\n", __func__, *dai_data->status_mask);
		return;
	}

	rc = afe_close(dai->id); /* can block */

	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close AFE port\n");

	pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
			*dai_data->status_mask);

	clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
}
示例#20
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;
}
static int snddev_ecodec_open(struct msm_snddev_info *dev_info)
{
	int rc;
	struct snddev_ecodec_drv_state *drv = &snddev_ecodec_drv;
	union afe_port_config afe_config;

	pr_debug("%s\n", __func__);

	mutex_lock(&drv->dev_lock);

	if (dev_info->opened) {
		pr_err("%s: ERROR: %s already opened\n", __func__,
				dev_info->name);
		mutex_unlock(&drv->dev_lock);
		return -EBUSY;
	}

	if (drv->ref_cnt != 0) {
		pr_debug("%s: opened %s\n", __func__, dev_info->name);
		drv->ref_cnt++;
		mutex_unlock(&drv->dev_lock);
		return 0;
	}

	pr_info("%s: opening %s\n", __func__, dev_info->name);

	rc = aux_pcm_gpios_request();
	if (rc < 0) {
		pr_err("%s: GPIO request failed\n", __func__);
		return rc;
	}

	clk_reset(drv->ecodec_clk, CLK_RESET_ASSERT);

	afe_config.pcm.mode = AFE_PCM_CFG_MODE_PCM;
	afe_config.pcm.sync = AFE_PCM_CFG_SYNC_INT;
	afe_config.pcm.frame = AFE_PCM_CFG_FRM_256BPF;
	afe_config.pcm.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD;
	afe_config.pcm.slot = 0;
	afe_config.pcm.data = AFE_PCM_CFG_CDATAOE_MASTER;

	rc = afe_open(PCM_RX, &afe_config, ECODEC_SAMPLE_RATE);
	if (rc < 0) {
		pr_err("%s: afe open failed for PCM_RX\n", __func__);
		goto err_rx_afe;
	}

	rc = afe_open(PCM_TX, &afe_config, ECODEC_SAMPLE_RATE);
	if (rc < 0) {
		pr_err("%s: afe open failed for PCM_TX\n", __func__);
		goto err_tx_afe;
	}

	rc = clk_set_rate(drv->ecodec_clk, 2048000);
	if (rc < 0) {
		pr_err("%s: clk_set_rate failed\n", __func__);
		goto err_clk;
	}

	clk_prepare_enable(drv->ecodec_clk);

	clk_reset(drv->ecodec_clk, CLK_RESET_DEASSERT);

	drv->ref_cnt++;
	mutex_unlock(&drv->dev_lock);

	return 0;

err_clk:
	afe_close(PCM_TX);
err_tx_afe:
	afe_close(PCM_RX);
err_rx_afe:
	aux_pcm_gpios_free();
	mutex_unlock(&drv->dev_lock);
	return -ENODEV;
}
示例#22
0
/* This function sends multi-channel HDMI configuration command and AFE
 * calibration which is only supported by QDSP6 on 8960 and onward.
 */
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
		   u32 rate)
{
	struct afe_port_start_command start;
	struct afe_audioif_config_command config;
	int ret;

	// [email protected] : Please refer to QCT case#01306695 regarding AFE recovery
	#ifdef CONFIG_LGE_AFE_RECOVERY
	int count = 0;
	#endif // CONFIG_LGE_AFE_RECOVERY

	if (!afe_config) {
		pr_err("%s: Error, no configuration data\n", __func__);
		ret = -EINVAL;
		return ret;
	}
	pr_debug("%s: %d %d\n", __func__, port_id, rate);

	if ((port_id == RT_PROXY_DAI_001_RX) ||
		(port_id == RT_PROXY_DAI_002_TX)) {
		pr_debug("%s: before incrementing pcm_afe_instance %d"\
				" port_id %d\n", __func__,
				pcm_afe_instance[port_id & 0x1], port_id);
		port_id = VIRTUAL_ID_TO_PORTID(port_id);
		pcm_afe_instance[port_id & 0x1]++;
		return 0;
	}
	if ((port_id == RT_PROXY_DAI_002_RX) ||
		(port_id == RT_PROXY_DAI_001_TX)) {
		pr_debug("%s: before incrementing proxy_afe_instance %d"\
				" port_id %d\n", __func__,
				proxy_afe_instance[port_id & 0x1], port_id);
		if (!afe_close_done[port_id & 0x1]) {
			/*close pcm dai corresponding to the proxy dai*/
			afe_close(port_id - 0x10);
			pcm_afe_instance[port_id & 0x1]++;
			pr_debug("%s: reconfigure afe port again\n", __func__);
		}
		proxy_afe_instance[port_id & 0x1]++;
		afe_close_done[port_id & 0x1] = false;
		port_id = VIRTUAL_ID_TO_PORTID(port_id);
	}

	ret = afe_q6_interface_prepare();
	if (IS_ERR_VALUE(ret))
		return ret;

	if (port_id == HDMI_RX) {
		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
		config.hdr.src_port = 0;
		config.hdr.dest_port = 0;
		config.hdr.token = 0;
		config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
	} else {

		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
		config.hdr.src_port = 0;
		config.hdr.dest_port = 0;
		config.hdr.token = 0;
		switch (port_id) {
		case SLIMBUS_0_RX:
		case SLIMBUS_0_TX:
		case SLIMBUS_1_RX:
		case SLIMBUS_1_TX:
		case SLIMBUS_2_RX:
		case SLIMBUS_2_TX:
		case SLIMBUS_3_RX:
		case SLIMBUS_3_TX:
		case SLIMBUS_4_RX:
		case SLIMBUS_4_TX:
			config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
		break;
		case MI2S_TX:
		case MI2S_RX:
		case SECONDARY_I2S_RX:
		case SECONDARY_I2S_TX:
		case PRIMARY_I2S_RX:
		case PRIMARY_I2S_TX:
			/* AFE_PORT_CMD_I2S_CONFIG command is not supported
			 * in the LPASS EL 1.0. So we have to distiguish
			 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
			 * AFE_PORT_AUDIO_IF_CONFIG	to use. If the format
			 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
			 * to make the backward compatible.
			 */
			pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
					 afe_config->mi2s.format);
			if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
				config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
			else
				config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
		break;
		default:
			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
		break;
		}
	}

	if (afe_validate_port(port_id) < 0) {

		pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
				port_id);
		ret = -EINVAL;
		goto fail_cmd;
	}
	config.port_id = port_id;
	config.port = *afe_config;

// [email protected] : Please refer to QCT case#01306695 regarding AFE recovery
#ifdef CONFIG_LGE_AFE_RECOVERY
send_cfg_cmd:
#endif // CONFIG_LGE_AFE_RECOVERY

	atomic_set(&this_afe.state, 1);
	atomic_set(&this_afe.status, 0);
	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
	if (ret < 0) {
		pr_err("%s: AFE enable for port %d failed\n", __func__,
				port_id);
		ret = -EINVAL;
		goto fail_cmd;
	}

	ret = wait_event_timeout(this_afe.wait,
			(atomic_read(&this_afe.state) == 0),
				msecs_to_jiffies(TIMEOUT_MS));

	if (!ret) {
		pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
		ret = -EINVAL;
		goto fail_cmd;
	}
	if (atomic_read(&this_afe.status) != 0) {
		pr_err("%s: config cmd failed\n", __func__);

		// [email protected] : Please refer to QCT case#01306695 regarding AFE recovery
		#ifdef CONFIG_LGE_AFE_RECOVERY
		if (count < 2) {
			afe_close(port_id);
			count++;
			goto send_cfg_cmd;
		}
		#endif // CONFIG_LGE_AFE_RECOVERY

		ret = -EINVAL;
		goto fail_cmd;
	}

	/* send AFE cal */
	afe_send_cal(port_id);
	afe_send_hw_delay(port_id, rate);

	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
	start.hdr.pkt_size = sizeof(start);
	start.hdr.src_port = 0;
	start.hdr.dest_port = 0;
	start.hdr.token = 0;
	start.hdr.opcode = AFE_PORT_CMD_START;
	start.port_id = port_id;
	start.gain = 0x2000;
	start.sample_rate = rate;

	atomic_set(&this_afe.state, 1);
	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);

	if (IS_ERR_VALUE(ret)) {
		pr_err("%s: AFE enable for port %d failed\n", __func__,
				port_id);
		ret = -EINVAL;
		goto fail_cmd;
	}

	ret = wait_event_timeout(this_afe.wait,
			(atomic_read(&this_afe.state) == 0),
				msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: wait_event timeout PORT START\n", __func__);
		ret = -EINVAL;
		goto fail_cmd;
	}

	if (this_afe.task != current)
		this_afe.task = current;

	pr_debug("task_name = %s pid = %d\n",
	this_afe.task->comm, this_afe.task->pid);
	return 0;

fail_cmd:
	return ret;
}
示例#23
0
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
		   u32 rate)
{
	struct afe_port_start_command start;
	struct afe_audioif_config_command config;
	int ret;

	if (!afe_config) {
		pr_err("%s: Error, no configuration data\n", __func__);
		ret = -EINVAL;
		return ret;
	}
	pr_info("%s: %d %d\n", __func__, port_id, rate);

	if ((port_id == RT_PROXY_DAI_001_RX) ||
		(port_id == RT_PROXY_DAI_002_TX)) {
		pr_debug("%s: before incrementing pcm_afe_instance %d"\
				" port_id %d\n", __func__,
				pcm_afe_instance[port_id & 0x1], port_id);
		port_id = VIRTUAL_ID_TO_PORTID(port_id);
		pcm_afe_instance[port_id & 0x1]++;
		return 0;
	}
	if ((port_id == RT_PROXY_DAI_002_RX) ||
		(port_id == RT_PROXY_DAI_001_TX)) {
		pr_debug("%s: before incrementing proxy_afe_instance %d"\
				" port_id %d\n", __func__,
				proxy_afe_instance[port_id & 0x1], port_id);
		if (!afe_close_done[port_id & 0x1]) {
			/*close pcm dai corresponding to the proxy dai*/
			afe_close(port_id - 0x10);
			pcm_afe_instance[port_id & 0x1]++;
			pr_debug("%s: reconfigure afe port again\n", __func__);
		}
		proxy_afe_instance[port_id & 0x1]++;
		afe_close_done[port_id & 0x1] = false;
		port_id = VIRTUAL_ID_TO_PORTID(port_id);
	}

	ret = afe_q6_interface_prepare();
	if (IS_ERR_VALUE(ret))
		return ret;

	if (port_id == HDMI_RX) {
		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
		config.hdr.src_port = 0;
		config.hdr.dest_port = 0;
		config.hdr.token = 0;
		config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
	} else {

		config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
		config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
		config.hdr.src_port = 0;
		config.hdr.dest_port = 0;
		config.hdr.token = 0;
		switch (port_id) {
		case SLIMBUS_0_RX:
		case SLIMBUS_0_TX:
		case SLIMBUS_1_RX:
		case SLIMBUS_1_TX:
		case SLIMBUS_2_RX:
		case SLIMBUS_2_TX:
		case SLIMBUS_3_RX:
		case SLIMBUS_3_TX:
		case SLIMBUS_4_RX:
		case SLIMBUS_4_TX:
			config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
		break;
		case MI2S_TX:
		case MI2S_RX:
		case SECONDARY_I2S_RX:
		case SECONDARY_I2S_TX:
		case PRIMARY_I2S_RX:
		case PRIMARY_I2S_TX:
			pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
					 afe_config->mi2s.format);
			if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
				config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
			else
				config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
		break;
		default:
			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
		break;
		}
	}

	if (afe_validate_port(port_id) < 0) {

		pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
				port_id);
		ret = -EINVAL;
		goto fail_cmd;
	}
	config.port_id = port_id;
	config.port = *afe_config;

	atomic_set(&this_afe.state, 1);
	atomic_set(&this_afe.status, 0);
	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
	if (ret < 0) {
		pr_err("%s: AFE enable for port %d failed\n", __func__,
				port_id);
		HTC_Q6_BUG();
		ret = -EINVAL;
		goto fail_cmd;
	}

	ret = wait_event_timeout(this_afe.wait,
			(atomic_read(&this_afe.state) == 0),
				msecs_to_jiffies(TIMEOUT_MS));

	if (!ret) {
		pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
		HTC_Q6_BUG();
		ret = -EINVAL;
		goto fail_cmd;
	}
	if (atomic_read(&this_afe.status) != 0) {
		pr_err("%s: config cmd failed\n", __func__);
		ret = -EINVAL;
		goto fail_cmd;
	}

	
	afe_send_cal(port_id);

	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
	start.hdr.pkt_size = sizeof(start);
	start.hdr.src_port = 0;
	start.hdr.dest_port = 0;
	start.hdr.token = 0;
	start.hdr.opcode = AFE_PORT_CMD_START;
	start.port_id = port_id;
	start.gain = 0x2000;
	start.sample_rate = rate;

	atomic_set(&this_afe.state, 1);
	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);

	if (IS_ERR_VALUE(ret)) {
		pr_err("%s: AFE enable for port %d failed\n", __func__,
				port_id);
		ret = -EINVAL;
		goto fail_cmd;
	}

	ret = wait_event_timeout(this_afe.wait,
			(atomic_read(&this_afe.state) == 0),
				msecs_to_jiffies(AFE_TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: wait_event timeout PORT START\n", __func__);
		HTC_Q6_BUG();
		ret = -EINVAL;
		goto fail_cmd;
	}

	if (this_afe.task != current)
		this_afe.task = current;

	pr_debug("task_name = %s pid = %d\n",
	this_afe.task->comm, this_afe.task->pid);
	return 0;

fail_cmd:
	return ret;
}
示例#24
0
static int snddev_ecodec_open(struct msm_snddev_info *dev_info)
{
	int rc;
	struct snddev_ecodec_drv_state *drv = &snddev_ecodec_drv;
	union afe_port_config afe_config;
#ifdef CONFIG_PANTECH_AUDIO_PRESTO_AUDIENCE2020 // jmlee	
       struct snddev_ecodec_state *ecodec;
       //int i;
#endif

	pr_debug("%s\n", __func__);

	mutex_lock(&drv->dev_lock);

	if (dev_info->opened) {
		pr_err("%s: ERROR: %s already opened\n", __func__,
				dev_info->name);
		mutex_unlock(&drv->dev_lock);
		return -EBUSY;
	}

	if (drv->ref_cnt != 0) {
		pr_debug("%s: opened %s\n", __func__, dev_info->name);
		drv->ref_cnt++;
		mutex_unlock(&drv->dev_lock);
		return 0;
	}

	pr_info("%s: opening %s\n", __func__, dev_info->name);

	rc = aux_pcm_gpios_request();
	if (rc < 0) {
		pr_err("%s: GPIO request failed\n", __func__);
		return rc;
	}

	clk_reset(drv->ecodec_clk, CLK_RESET_ASSERT);

	afe_config.pcm.mode = AFE_PCM_CFG_MODE_PCM;
	afe_config.pcm.sync = AFE_PCM_CFG_SYNC_INT;
	afe_config.pcm.frame = AFE_PCM_CFG_FRM_256BPF;
	afe_config.pcm.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD;
	afe_config.pcm.slot = 0;
	afe_config.pcm.data = AFE_PCM_CFG_CDATAOE_MASTER;

	rc = afe_open(PCM_RX, &afe_config, ECODEC_SAMPLE_RATE);
	if (rc < 0) {
		pr_err("%s: afe open failed for PCM_RX\n", __func__);
		goto err_rx_afe;
	}

	rc = afe_open(PCM_TX, &afe_config, ECODEC_SAMPLE_RATE);
	if (rc < 0) {
		pr_err("%s: afe open failed for PCM_TX\n", __func__);
		goto err_tx_afe;
	}

	rc = clk_set_rate(drv->ecodec_clk, 2048000);
	if (rc < 0) {
		pr_err("%s: clk_set_rate failed\n", __func__);
		goto err_clk;
	}

	clk_enable(drv->ecodec_clk);

	clk_reset(drv->ecodec_clk, CLK_RESET_DEASSERT);

	drv->ref_cnt++;
	mutex_unlock(&drv->dev_lock);

#ifdef CONFIG_PANTECH_AUDIO_PRESTO_AUDIENCE2020 // jmlee	
	/* audience enable */
       ecodec = dev_info->private_data;
	if ((ecodec->data->pamp_on) && (!ecodec_audience_enable))
	{
	     ecodec->data->pamp_on();
	     ecodec_audience_enable = 1;

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

	}

#endif	

	return 0;

err_clk:
	afe_close(PCM_TX);
err_tx_afe:
	afe_close(PCM_RX);
err_rx_afe:
	aux_pcm_gpios_free();
	mutex_unlock(&drv->dev_lock);
	return -ENODEV;
}