static int msm_dai_q6_auxpcm_prepare(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;

	mutex_lock(&aux_pcm_mutex);

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

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

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

	rc = afe_q6_interface_prepare();
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to open AFE APR\n");

	/*
	 * For AUX PCM Interface the below sequence of clk
	 * settings and afe_open is a strict requirement.
	 *
	 * Also using afe_open instead of afe_port_start_nowait
	 * to make sure the port is open before deasserting the
	 * clock line. This is required because pcm register is
	 * not written before clock deassert. Hence the hw does
	 * not get updated with new setting if the below clock
	 * assert/deasset and afe_open sequence is not followed.
	 */

	afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);

	afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);

	mutex_unlock(&aux_pcm_mutex);

	return rc;
}
static int msm_dai_q6_auxpcm_prepare(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;

	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;

	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_q6_interface_prepare();
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to open AFE APR\n");

		rc = afe_q6_interface_prepare();
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to open AFE APR\n");

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

		/*
		 * For AUX PCM Interface the below sequence of clk
		 * settings and afe_open is a strict requirement.
		 *
		 * Also using afe_open instead of afe_port_start_nowait
		 * to make sure the port is open before deasserting the
		 * clock line. This is required because pcm register is
		 * not written before clock deassert. Hence the hw does
		 * not get updated with new setting if the below clock
		 * assert/deasset and afe_open sequence is not followed.
		 */

		clk_reset(pcm_clk, CLK_RESET_ASSERT);

		afe_open(dai->id, &dai_data->port_config,
			dai_data->rate);
		set_bit(STATUS_PORT_STARTED,
			dai_data->status_mask);

		afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);

		rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
		if (rc < 0) {
			pr_err("%s: clk_set_rate failed\n", __func__);
			return rc;
		}

		clk_enable(pcm_clk);
		clk_reset(pcm_clk, CLK_RESET_DEASSERT);

	}
	return rc;
}
示例#3
0
static int snddev_hdmi_open(struct msm_snddev_info *dev_info)
{
	int rc = 0;
	union afe_port_config afe_config;
	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;

	mutex_lock(&snddev_hdmi_lock);

	if (snddev_hdmi_active) {
		pr_err("HDMI snddev already active\n");
		mutex_unlock(&snddev_hdmi_lock);
		return -EBUSY;
	}

	if (snddev_hdmi_data->on_apps) {
		snddev_hdmi_active = 1;
		pr_debug("%s open done\n", dev_info->name);
		mutex_unlock(&snddev_hdmi_lock);
		return 0;
	}

	afe_config.hdmi.channel_mode = snddev_hdmi_data->channel_mode;
	afe_config.hdmi.bitwidth = 16;
	afe_config.hdmi.data_type = 0;
	rc = afe_open(snddev_hdmi_data->copp_id, &afe_config,
		dev_info->sample_rate);

	if (rc < 0) {
		pr_err("afe_open failed\n");
		mutex_unlock(&snddev_hdmi_lock);
		return -EINVAL;
	}
	snddev_hdmi_active = 1;

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

	mutex_unlock(&snddev_hdmi_lock);

	return 0;
}
static int afe_start(struct pcm *pcm)
{
	union afe_port_config port_config;
	port_config.rtproxy.num_ch =
			pcm->channel_count;

	pr_debug("channel %d entered,port: %d,rate: %d\n",
	port_config.rtproxy.num_ch, RT_PROXY_DAI_001_TX, pcm->sample_rate);

	port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
	port_config.rtproxy.interleaved = 1;
	port_config.rtproxy.frame_sz = pcm->buffer_size;
	port_config.rtproxy.jitter =
				port_config.rtproxy.frame_sz/2;
	port_config.rtproxy.lw_mark = 0;
	port_config.rtproxy.hw_mark = 0;
	port_config.rtproxy.rsvd = 0;
	afe_open(RT_PROXY_DAI_001_TX, &port_config, pcm->sample_rate);
	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;
}
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;
}
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;
}
示例#8
0
static int snddev_mi2s_open(struct msm_snddev_info *dev_info)
{
	int rc = 0;
	union afe_port_config afe_config;
	u8 channels;
	u8 num_of_sd_lines = 0;
	struct snddev_mi2s_drv_state *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;
	}

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

	rc =  clk_set_rate(drv->tx_osrclk,
			 SNDDEV_MI2S_CLK_RATE(dev_info->sample_rate));
	if (IS_ERR_VALUE(rc)) {
		pr_err("ERROR setting osr clock\n");
		return -ENODEV;
	}
	clk_prepare_enable(drv->tx_osrclk);

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

	rc =  clk_set_rate(drv->tx_bitclk, 8);
	if (IS_ERR_VALUE(rc)) {
		pr_err("ERROR setting bit clock\n");
		clk_disable_unprepare(drv->tx_osrclk);
		return -ENODEV;
	}
	clk_prepare_enable(drv->tx_bitclk);

	afe_config.mi2s.bitwidth = 16;

	if (snddev_mi2s_data->channel_mode == 1)
		channels = AFE_MI2S_MONO;
	else if (snddev_mi2s_data->channel_mode == 2)
		channels = AFE_MI2S_STEREO;
	else if (snddev_mi2s_data->channel_mode == 4)
		channels = AFE_MI2S_4CHANNELS;
	else if (snddev_mi2s_data->channel_mode == 6)
		channels = AFE_MI2S_6CHANNELS;
	else if (snddev_mi2s_data->channel_mode == 8)
		channels = AFE_MI2S_8CHANNELS;
	else {
		pr_err("ERROR: Invalid MI2S channel mode\n");
		goto error_invalid_data;
	}

	num_of_sd_lines = num_of_bits_set(snddev_mi2s_data->sd_lines);

	switch (num_of_sd_lines) {
	case 1:
		switch (snddev_mi2s_data->sd_lines) {
		case MI2S_SD0:
			afe_config.mi2s.line = AFE_I2S_SD0;
			break;
		case MI2S_SD1:
			afe_config.mi2s.line = AFE_I2S_SD1;
			break;
		case MI2S_SD2:
			afe_config.mi2s.line = AFE_I2S_SD2;
			break;
		case MI2S_SD3:
			afe_config.mi2s.line = AFE_I2S_SD3;
			break;
		default:
			pr_err("%s: invalid SD line\n",
			__func__);
			goto error_invalid_data;
		}
		if (channels != AFE_MI2S_STEREO &&
		channels != AFE_MI2S_MONO) {
			pr_err("%s: for one SD line, channel "
			"must be 1 or 2\n", __func__);
			goto error_invalid_data;
		}
		afe_config.mi2s.channel = channels;
		break;
	case 2:
		switch (snddev_mi2s_data->sd_lines) {
		case MI2S_SD0 | MI2S_SD1:
			afe_config.mi2s.line = AFE_I2S_QUAD01;
			break;
		case MI2S_SD2 | MI2S_SD3:
			afe_config.mi2s.line = AFE_I2S_QUAD23;
			break;
		default:
			pr_err("%s: invalid SD line\n",
			__func__);
			goto error_invalid_data;
		}
		if (channels != AFE_MI2S_4CHANNELS) {
			pr_err("%s: for two SD lines, channel "
			"must be 1 and 2 or 3 and 4\n", __func__);
			goto error_invalid_data;
		}
		break;
	case 3:
		switch (snddev_mi2s_data->sd_lines) {
		case MI2S_SD0 | MI2S_SD1 | MI2S_SD2:
			afe_config.mi2s.line = AFE_I2S_6CHS;
			break;
		default:
			pr_err("%s: invalid SD lines\n",
			__func__);
			goto error_invalid_data;
		}
		if (channels != AFE_MI2S_6CHANNELS) {
			pr_err("%s: for three SD lines, lines "
			"must be 1, 2, and 3\n", __func__);
			goto error_invalid_data;
		}
		break;
	case 4:
		switch (snddev_mi2s_data->sd_lines) {
		case MI2S_SD0 | MI2S_SD1 | MI2S_SD2 | MI2S_SD3:
			afe_config.mi2s.line = AFE_I2S_8CHS;
			break;
		default:
			pr_err("%s: invalid SD lines\n",
			__func__);
			goto error_invalid_data;
		}

		if (channels != AFE_MI2S_8CHANNELS) {
			pr_err("%s: for four SD lines, lines "
			"must be 1, 2, 3, and 4\n", __func__);
			goto error_invalid_data;
		}
		break;
	default:
		pr_err("%s: invalid SD lines\n", __func__);
		goto error_invalid_data;
	}
	afe_config.mi2s.ws = 1;
	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;

	rc = afe_open(snddev_mi2s_data->copp_id, &afe_config,
		dev_info->sample_rate);

	if (rc < 0) {
		pr_err("%s:  afe_open failed\n", __func__);
		goto error_invalid_data;
	}

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

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

	return rc;

error_invalid_data:

	clk_disable_unprepare(drv->tx_bitclk);
	clk_disable_unprepare(drv->tx_osrclk);
	return -EINVAL;
}
static int msm_dai_q6_auxpcm_prepare(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;
	struct msm_dai_auxpcm_pdata *auxpcm_pdata =
			(struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
	unsigned long pcm_clk_rate;

	mutex_lock(&aux_pcm_mutex);

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

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

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

	rc = afe_q6_interface_prepare();
	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to open AFE APR\n");

	/*
	 * For AUX PCM Interface the below sequence of clk
	 * settings and afe_open is a strict requirement.
	 *
	 * Also using afe_open instead of afe_port_start_nowait
	 * to make sure the port is open before deasserting the
	 * clock line. This is required because pcm register is
	 * not written before clock deassert. Hence the hw does
	 * not get updated with new setting if the below clock
	 * assert/deasset and afe_open sequence is not followed.
	 */

	clk_reset(pcm_clk, CLK_RESET_ASSERT);

	afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);

	afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
	if (dai_data->rate == 8000) {
		pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
	} else if (dai_data->rate == 16000) {
		pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
	} else {
		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
			  dai_data->rate);
		return -EINVAL;
	}

	rc = clk_set_rate(pcm_clk, pcm_clk_rate);
	if (rc < 0) {
		pr_err("%s: clk_set_rate failed\n", __func__);
		return rc;
	}

	clk_prepare_enable(pcm_clk);
	clk_reset(pcm_clk, CLK_RESET_DEASSERT);

	mutex_unlock(&aux_pcm_mutex);

	return rc;
}
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec)
{
	int trc;
	int rc_clk;
	int afe_channel_mode;
	union afe_port_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;;

	wake_lock(&drv->tx_idlelock);

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

	if (support_aic3254_use_mclk) {
		rc_clk = snddev_icodec_rxclk_enable(icodec, 1);
		if (IS_ERR_VALUE(rc_clk)) {
			pr_aud_err("%s Enable RX master clock Error\n", \
					__func__);
			goto error_invalid_osrclk;
		}
	}

	msm_snddev_tx_mclk_request();

	drv->tx_osrclk = clk_get(0, "i2s_mic_osr_clk");
	if (IS_ERR(drv->tx_osrclk)) {
		pr_aud_err("%s master clock Error\n", __func__);
		goto error_invalid_osrclk;
	}

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

	clk_enable(drv->tx_osrclk);

	drv->tx_bitclk = clk_get(0, "i2s_mic_bit_clk");
	if (IS_ERR(drv->tx_bitclk)) {
		pr_aud_err("%s clock Error\n", __func__);
		goto error_invalid_bitclk;
	}

	/* ***************************************
	 * 1. CPU MASTER MODE:
	 *     Master clock = Sample Rate * OSR rate bit clock
	 * OSR Rate bit clock = bit/sample * channel master
	 * clock / bit clock = divider value = 8
	 *
	 * 2. CPU SLAVE MODE:
	 *     bitclk = 0
	 * *************************************** */
	if (msm_codec_i2s_slave_mode) {
		pr_debug("%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_enable(drv->tx_bitclk);

	if (support_aic3254) {
		if (aic3254_ops->aic3254_set_mode) {
			if (msm_get_call_state() == 1)
				aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX,
					icodec->data->aic3254_voc_id);
			else
				aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX,
					icodec->data->aic3254_id);
		}
	}
	if (support_adie) {
		/* Enable ADIE */
		trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
		if (IS_ERR_VALUE(trc))
			pr_aud_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;
	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 && support_adie) {
		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);
	}

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

	icodec->enabled = 1;

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

error_invalid_bitclk:
	clk_disable(drv->tx_osrclk);
error_invalid_freq:
error_invalid_osrclk:
	if (icodec->data->pamp_on)
		icodec->data->pamp_on(0);
	msm_snddev_tx_mclk_free();

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

	wake_unlock(&drv->tx_idlelock);
	return -ENODEV;
}
示例#11
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;
}
示例#12
0
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec)
{
	int trc;
	int rc_clk;
	int afe_channel_mode;
	union afe_port_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;

	wake_lock(&drv->rx_idlelock);

	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);
	}

	if (support_aic3254_use_mclk) {
		rc_clk = snddev_icodec_rxclk_enable(icodec, 1);
		if (IS_ERR_VALUE(rc_clk)) {
			pr_aud_err("%s Enable RX master clock Error\n", \
					__func__);
			goto error_invalid_freq;
		}
	} else {
		msm_snddev_rx_mclk_request();

		drv->rx_osrclk = clk_get(0, "i2s_spkr_osr_clk");
		if (IS_ERR(drv->rx_osrclk))
			pr_aud_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_aud_err("ERROR setting m clock1\n");
			goto error_invalid_freq;
		}

		clk_enable(drv->rx_osrclk);
	}

	drv->rx_bitclk = clk_get(0, "i2s_spkr_bit_clk");
	if (IS_ERR(drv->rx_bitclk))
		pr_aud_err("%s clock Error\n", __func__);

	/* ***************************************
	 * 1. CPU MASTER MODE:
	 *     Master clock = Sample Rate * OSR rate bit clock
	 * OSR Rate bit clock = bit/sample * channel master
	 * clock / bit clock = divider value = 8
	 *
	 * 2. CPU SLAVE MODE:
	 *     bitclk = 0
	 * *************************************** */

	if (msm_codec_i2s_slave_mode) {
		pr_debug("%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_aud_err("ERROR setting m clock1\n");
		goto error_adie;
	}
	clk_enable(drv->rx_bitclk);

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

	if (support_aic3254) {
		if (aic3254_ops->aic3254_set_mode) {
			if (msm_get_call_state() == 1)
				aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX,
					icodec->data->aic3254_voc_id);
			else
				aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX,
					icodec->data->aic3254_id);
		}
	}
	if (support_adie) {
		/* Configure ADIE */
		trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
		if (IS_ERR_VALUE(trc))
			pr_aud_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;
	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_aud_err("%s: afe open failed, trc = %d\n", __func__, trc);

	if (support_adie) {
		/* 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)
		icodec->data->pamp_on(1);

	icodec->enabled = 1;

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

error_adie:
	clk_disable(drv->rx_bitclk);
	clk_disable(drv->rx_osrclk);
error_invalid_freq:

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

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