Beispiel #1
0
static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params,
				struct snd_soc_dai *dai)
{
	struct device *dev = dai->dev;
	struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
	unsigned int mask = 0, val = 0;
	int ret, srate, spdifclock;
	u32 ch_sta[2] = {0, 0};

	mask |= TEGRA20_SPDIF_CTRL_PACK |
		TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		val |= TEGRA20_SPDIF_CTRL_PACK |
		       TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
		break;
	default:
		return -EINVAL;
	}

	regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val);

	srate = params_rate(params);
	switch (params_rate(params)) {
	case 32000:
		spdifclock = 4096000;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
		break;
	case 44100:
		spdifclock = 5644800;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
		break;
	case 48000:
		spdifclock = 6144000;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
		break;
	case 88200:
		spdifclock = 11289600;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
		break;
	case 96000:
		spdifclock = 12288000;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
		break;
	case 176400:
		spdifclock = 22579200;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
		break;
	case 192000:
		spdifclock = 24576000;
		ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
		ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
		break;
	default:
		return -EINVAL;
	}

	ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
	if (ret) {
		dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
		return ret;
	}

	clk_enable(spdif->clk_spdif_out);

	mask = TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
	regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CH_STA_TX_A, mask, ch_sta[0]);
	mask = TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
	regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CH_STA_TX_B, mask, ch_sta[1]);

	clk_disable(spdif->clk_spdif_out);

	ret = tegra_hdmi_setup_audio_freq_source(srate, SPDIF);
	if (ret) {
		dev_err(dev, "Can't set HDMI audio freq source: %d\n", ret);
		return ret;
	}

	return 0;
}
static int tegra30_spdif_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params,
				struct snd_soc_dai *dai)
{
	struct device *dev = substream->pcm->card->dev;
	struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
	int ret, srate, spdifclock;

	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
		dev_err(dev, "spdif capture is not supported\n");
		return -EINVAL;
	}

	spdif->reg_ctrl &= ~TEGRA30_SPDIF_CTRL_BIT_MODE_MASK;
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_PACK_ENABLE;
		spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_BIT_MODE_16BIT;
		break;
	default:
		return -EINVAL;
	}

	srate = params_rate(params);
	spdif->reg_ch_sta_a &= ~TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
	spdif->reg_ch_sta_b &= ~TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
	switch (srate) {
	case 32000:
		spdifclock = 4096000;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
		break;
	case 44100:
		spdifclock = 5644800;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
		break;
	case 48000:
		spdifclock = 6144000;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
		break;
	case 88200:
		spdifclock = 11289600;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
		break;
	case 96000:
		spdifclock = 12288000;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
		break;
	case 176400:
		spdifclock = 22579200;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
		break;
	case 192000:
		spdifclock = 24576000;
		spdif->reg_ch_sta_a |=
			TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
		spdif->reg_ch_sta_b |=
			TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
		break;
	default:
		return -EINVAL;
	}

	ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
	if (ret) {
		dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
		return ret;
	}

	tegra30_spdif_enable_clocks(spdif);

	tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_A,
						spdif->reg_ch_sta_a);
	tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_B,
						spdif->reg_ch_sta_b);

	tegra30_spdif_disable_clocks(spdif);

	ret = tegra_hdmi_setup_audio_freq_source(srate, SPDIF);
	if (ret) {
		dev_err(dev, "Can't set HDMI audio freq source: %d\n", ret);
		return ret;
	}

	return 0;
}