static int tegra30_dam_runtime_resume(struct device *dev)
{
	struct tegra30_dam_context *dam = dev_get_drvdata(dev);
	int ret;

	tegra30_ahub_enable_clocks();
	ret = clk_prepare_enable(dam->dam_clk);
	if (ret) {
		dev_err(dev, "clk_enable failed: %d\n", ret);
		return ret;
	}
	regcache_cache_only(dam->regmap, false);

	return 0;
}
示例#2
0
int tegra30_ahub_set_rx_cif_stereo_conv(enum tegra30_ahub_rxcif rxcif)
{
	int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
	unsigned int reg, val;

	tegra30_ahub_enable_clocks();

	reg = TEGRA30_AHUB_CIF_RX_CTRL +
	      (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
	val = tegra30_apbif_read(reg);
	val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
	val |= TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG;
	tegra30_apbif_write(reg, val);

	tegra30_ahub_disable_clocks();

	return 0;
}
static int tegra30_dam_show(struct seq_file *s, void *unused)
{
#define REG(r) { r, #r }
	static const struct {
		int offset;
		const char *name;
	} regs[] = {
		REG(TEGRA30_DAM_CTRL),
		REG(TEGRA30_DAM_CLIP),
		REG(TEGRA30_DAM_CLIP_THRESHOLD),
		REG(TEGRA30_DAM_AUDIOCIF_OUT_CTRL),
		REG(TEGRA30_DAM_CH0_CTRL),
		REG(TEGRA30_DAM_CH0_CONV),
		REG(TEGRA30_DAM_AUDIOCIF_CH0_CTRL),
		REG(TEGRA30_DAM_CH1_CTRL),
		REG(TEGRA30_DAM_CH1_CONV),
		REG(TEGRA30_DAM_AUDIOCIF_CH1_CTRL),
	};
#undef REG

	struct tegra30_dam_context *dam = s->private;
	int i;

	tegra30_ahub_enable_clocks();
	clk_enable(dam->dam_clk);

	for (i = 0; i < ARRAY_SIZE(regs); i++) {
		u32 val = tegra30_dam_readl(dam, regs[i].offset);
		seq_printf(s, "%s = %08x\n", regs[i].name, val);
	}

	clk_disable(dam->dam_clk);
	tegra30_ahub_disable_clocks();

	return 0;
}
static int tegra_dmic_dai_startup(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct tegra_dmic *dmic = snd_soc_dai_get_drvdata(dai);
	u32 dmic_cif_id;
	int ret = 0;

	mutex_lock(&dmic->mutex);

	tegra30_ahub_enable_clocks();
	ret = clk_enable(dmic->clk);
	if (ret < 0)
		dev_err(dmic->dev, "Can't enable DMIC clock\n");

	/* Obtain Rx FIFOs and setup connections. */

	ret = tegra30_ahub_allocate_rx_fifo(&dmic->rx_cif,
		&dmic->capture_dma_data.addr,
		&dmic->capture_dma_data.req_sel);
	dmic->capture_dma_data.wrap = 4;
	dmic->capture_dma_data.width = 32;

	if (dai->id == TEGRA_DMIC_FRONT)
		dmic_cif_id = TEGRA30_AHUB_TXCIF_DMIC0_TX0;
	else if (dai->id == TEGRA_DMIC_BACK)
		dmic_cif_id = TEGRA30_AHUB_TXCIF_DMIC1_TX0;
	else
		return -EINVAL;

	tegra30_ahub_set_rx_cif_source(dmic->rx_cif,
		dmic_cif_id);

	mutex_unlock(&dmic->mutex);

	return ret;
}
static void tegra30_spdif_enable_clocks(struct tegra30_spdif *spdif)
{
	clk_enable(spdif->clk_spdif_out);
	tegra30_ahub_enable_clocks();
}
static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(rtd->card);
	struct codec_config *codec_info;
	struct codec_config *bb_info;
	struct codec_config *hifi_info;
	int codec_index;

	if (!i2s->is_dam_used)
		return 0;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/*
		*make apbif tx to i2s rx connection if this is the only client
		*using i2s for playback
		*/
		if (i2s->playback_ref_count == 1) {
			tegra30_ahub_set_rx_cif_source(
				TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
				i2s->txcif);
			tegra30_ahub_enable_clocks();
		}

	} else {
		i2s->is_call_mode_rec = machine->is_call_mode;
		if (!i2s->is_call_mode_rec)
			return 0;

		if (machine->is_device_bt)
			codec_index = BT_SCO;
		else
			codec_index = VOICE_CODEC;

		codec_info = &machine->codec_info[codec_index];
		bb_info = &machine->codec_info[BASEBAND];
		hifi_info = &machine->codec_info[HIFI_CODEC];

		/* allocate a dams for voice call recording */

		i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();

		if (i2s->call_record_dam_ifc < 0)
			return i2s->call_record_dam_ifc;

		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
			TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
			TEGRA30_DAM_CHIN1);
		tegra30_dam_enable_clock(i2s->call_record_dam_ifc);

		i2s->call_record_dam_ifc2 = tegra30_dam_allocate_controller();

		if (i2s->call_record_dam_ifc2 < 0)
			return i2s->call_record_dam_ifc2;

		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
			TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
			TEGRA30_DAM_CHIN1);
		tegra30_dam_enable_clock(i2s->call_record_dam_ifc2);

		/* configure the dams */
		/* DAM0 SRC bb rate to hifi rate */
		tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc,
			codec_info->rate, codec_info->channels,
			codec_info->bitsize, 1, hifi_info->rate,
			hifi_info->channels, hifi_info->bitsize);
		/* DAM1 UL + DL Mix */
		tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc2,
			codec_info->rate, codec_info->channels,
			codec_info->bitsize, 1, bb_info->rate,
			bb_info->channels, bb_info->bitsize);

		/* setup the connections for voice call record */
		tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
			(i2s->call_record_dam_ifc2*2),
			TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
			(i2s->call_record_dam_ifc2*2),
			TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
			(i2s->call_record_dam_ifc*2),
			TEGRA30_AHUB_TXCIF_DAM0_TX0 +
			i2s->call_record_dam_ifc2);
		tegra30_ahub_set_rx_cif_source(i2s->rxcif,
			TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
#ifndef CONFIG_ARCH_TEGRA_3x_SOC
		/* Configure DAM0 for SRC */
		if (bb_info->rate != hifi_info->rate) {
			tegra30_dam_write_coeff_ram(i2s->call_record_dam_ifc,
						bb_info->rate, hifi_info->rate);
			tegra30_dam_set_farrow_param(i2s->call_record_dam_ifc,
						bb_info->rate, hifi_info->rate);
			tegra30_dam_set_biquad_fixed_coef(
						i2s->call_record_dam_ifc);
			tegra30_dam_enable_coeff_ram(i2s->call_record_dam_ifc);
			tegra30_dam_set_filter_stages(i2s->call_record_dam_ifc,
							bb_info->rate,
							hifi_info->rate);
		}
#endif
		/* enable the dam */
		tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
				TEGRA30_DAM_CHIN1);
		tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
				TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_enable(i2s->call_record_dam_ifc2,
					TEGRA30_DAM_ENABLE,
					TEGRA30_DAM_CHIN1);
		tegra30_dam_enable(i2s->call_record_dam_ifc2,
					TEGRA30_DAM_ENABLE,
					TEGRA30_DAM_CHIN0_SRC);
	}

	return 0;
}