Exemplo n.º 1
0
static void tegra30_spdif_stop_playback(struct tegra30_spdif *spdif)
{
	tegra30_ahub_disable_tx_fifo(spdif->txcif);
	spdif->reg_ctrl &= ~(TEGRA30_SPDIF_CTRL_TX_EN_ENABLE |
				TEGRA30_SPDIF_CTRL_TC_EN_ENABLE);
	tegra30_spdif_write(spdif, TEGRA30_SPDIF_CTRL, spdif->reg_ctrl);
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
static __devinit int tegra30_spdif_platform_probe(struct platform_device *pdev)
{
	struct tegra30_spdif *spdif;
	struct resource *mem, *memregion;
	int ret;
	u32 reg_val;

	spdif = kzalloc(sizeof(struct tegra30_spdif), GFP_KERNEL);
	if (!spdif) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: Can't allocate tegra30_spdif\n");
#endif
		dev_err(&pdev->dev, "Can't allocate tegra30_spdif\n");
		ret = -ENOMEM;
		goto exit;
	}
	dev_set_drvdata(&pdev->dev, spdif);

	spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
	if (IS_ERR(spdif->clk_spdif_out)) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: Can't retrieve spdif clock\n");
#endif
		dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
		ret = PTR_ERR(spdif->clk_spdif_out);
		goto err_free;
	}

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: No memory resource\n");
#endif
		dev_err(&pdev->dev, "No memory resource\n");
		ret = -ENODEV;
		goto err_clk_put_spdif;
	}

	memregion = request_mem_region(mem->start, resource_size(mem),
					DRV_NAME);
	if (!memregion) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: Memory region already claimed\n");
#endif
		dev_err(&pdev->dev, "Memory region already claimed\n");
		ret = -EBUSY;
		goto err_clk_put_spdif;
	}

	spdif->regs = ioremap(mem->start, resource_size(mem));
	if (!spdif->regs) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: ioremap failed\n");
#endif
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err_release;
	}

	tegra30_spdif_enable_clocks(spdif);

	reg_val = TEGRA30_SPDIF_CIF_TXD_CTRL_DIRECTION_RXCIF |
		TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT16 |
		TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT16 |
		TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH2 |
		TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH2 |
		(3 << TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_SHIFT);

	tegra30_spdif_write(spdif, TEGRA30_SPDIF_CIF_TXD_CTRL, reg_val);

	tegra30_spdif_disable_clocks(spdif);

	ret = snd_soc_register_dai(&pdev->dev, &tegra30_spdif_dai);
	if (ret) {
#if HDMI_DEBUG
		printk("HDMI_DEBUG: Could not register DAI: %d\n", ret);
#endif
		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
		ret = -ENOMEM;
		goto err_unmap;
	}

	tegra30_spdif_debug_add(spdif);

	return 0;

err_unmap:
	iounmap(spdif->regs);
err_release:
	release_mem_region(mem->start, resource_size(mem));
err_clk_put_spdif:
	clk_put(spdif->clk_spdif_out);
err_free:
	kfree(spdif);
exit:
	return ret;
}