int spdif_clock_disable(int ifc, int mode)
{
	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);

	if (!spinfo)
		return -ENOENT;

	if (spinfo->spdev[mode].clk_refs > 0) {
		spinfo->spdev[mode].clk_refs--;

		if (spinfo->spdev[mode].clk_refs == 0) {
			if (spinfo->spclk.hda2codec_clk)
				clk_disable(spinfo->spclk.hda2codec_clk);
			if (mode == AUDIO_TX_MODE) {
				if (spinfo->spclk.spdifout_clk)
					clk_disable(spinfo->spclk.spdifout_clk);
			} else {
				if (spinfo->spclk.spdifin_clk)
					clk_disable(spinfo->spclk.spdifin_clk);
			}
		}
	}

	audio_switch_disable_clock();

	SPDIF_DEBUG_PRINT("%s clock count 0x%x\n",
			__func__, spinfo->spdev[mode].clk_refs);
	return 0;
}
static int spdif_open(void)
{
	int err = 0;

	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);
	if (!spinfo) {

		spinfo =
		kzalloc(sizeof(struct spdif_controller_info), GFP_KERNEL);

		if (!spinfo)
			return -ENOMEM;

		spinfo->spclk.spdifout_clk = clk_get_sys("spdif_out", NULL);
		if (IS_ERR_OR_NULL(spinfo->spclk.spdifout_clk)) {
			err = -ENOENT;
			spinfo->spclk.spdifout_clk = 0;
			goto fail_spdif_open;
		}

		spinfo->spclk.spdifin_clk = clk_get_sys("spdif_in", NULL);
		if (IS_ERR_OR_NULL(spinfo->spclk.spdifin_clk)) {
			err = -ENOENT;
			spinfo->spclk.spdifin_clk = 0;
			goto fail_spdif_open;
		}

#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
		spinfo->spclk.hda2codec_clk = clk_get_sys("hda2codec_2x", NULL);
		if (IS_ERR_OR_NULL(spinfo->spclk.hda2codec_clk)) {
			pr_err("couldn't get hda2codec_2x clock\n");
			err = -ENODEV;
			spinfo->spclk.hda2codec_clk = 0;
			goto fail_spdif_open;
		}

		spinfo->reg_cache =
			kzalloc(sizeof(int)*SPDIF_REG_INDEX_MAX, GFP_KERNEL);
#else
		spinfo->reg_cache =
			kzalloc(sizeof(struct spdif_regs_cache), GFP_KERNEL);
#endif

		if (!spinfo->reg_cache)
			goto fail_spdif_open;

		spinfo->refcnt++;
	}

	spinfo->refcnt++;

	SPDIF_DEBUG_PRINT(" %s --\n", __func__);
	return err;

fail_spdif_open:

	spdif_close(0);
	return err;
}
int spdif_clock_enable(int ifc, int mode)
{
	int err = 0;

	if (!spinfo)
		return -ENOENT;

	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);

	err = audio_switch_enable_clock();
	if (err)
		return err;

	if (spinfo->spdev[mode].clk_refs > 0) {
		spinfo->spdev[mode].clk_refs++;

	} else {

		spdif_clock_set_rate(0, mode,
				spinfo->spdev[mode].ch_prop.clk_rate);

		if (mode == AUDIO_TX_MODE) {
			if (clk_enable(spinfo->spclk.spdifout_clk)) {
				err = PTR_ERR(spinfo->spclk.spdifout_clk);
				goto spdif_clock_enable_failed;
			}
		} else {
			if (clk_enable(spinfo->spclk.spdifin_clk)) {
				err = PTR_ERR(spinfo->spclk.spdifin_clk);
				goto spdif_clock_enable_failed;
			}
		}

		if (spinfo->spclk.hda2codec_clk &&
			clk_enable(spinfo->spclk.hda2codec_clk)) {
			pr_err("failed to enable hda2codec_2x clock\n");
			err = PTR_ERR(spinfo->spclk.hda2codec_clk);
			goto spdif_clock_enable_failed;
		}

		spinfo->spdev[mode].clk_refs++;
	}

	SPDIF_DEBUG_PRINT("%s clk cnt 0x%x\n",
			__func__, spinfo->spdev[mode].clk_refs);
	return err;

spdif_clock_enable_failed:

	spdif_clock_disable(0, mode);
	return err;
}
int spdif_resume(int ifc)
{
	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);
	/* FIXME : check for Rx mode if needed */
	spdif_clock_enable(0, AUDIO_TX_MODE);
	audio_switch_resume();
	spdif_restore_regs(spinfo->base);

	return 0;
}
int spdif_init(unsigned long base, phys_addr_t phy_base, int mode,
			struct tegra_spdif_property* spdifprop)
{
	int err = 0;

	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);
	if (spdif_open())
		return err;

	/* open audio_switch first */
	err = audio_switch_open();
	if (err) {
		spdif_close(0);
		return err;
	}

	spinfo->base = base;
	spinfo->phy_base = phy_base;
	spinfo->spdev[mode].ch_prop.bit_size = spdifprop->bit_size;
	spinfo->spdev[mode].ch_prop.channels = spdifprop->channels;
	spinfo->spdev[mode].ch_prop.clk_rate = spdifprop->clk_rate;
	spinfo->spdev[mode].ch_prop.sample_rate = spdifprop->sample_rate;
	spdif_clock_set_parent(0, mode, 0);

	err = spdif_clock_enable(0, mode);
	if (err) {
		audio_switch_close();
		spdif_close(0);
		return err;
	}

	spdif_initialize(base, mode);

	spdif_set_sample_rate(0, mode, spdifprop->sample_rate);

	spdif_clock_disable(0, mode);
	SPDIF_DEBUG_PRINT(" %s --\n", __func__);
	return 0;
}
int spdif_suspend(int ifc)
{
	SPDIF_DEBUG_PRINT(" %s ++\n", __func__);

	/* FIXME : check for Rx mode if needed */
	if (spinfo->spdev[AUDIO_TX_MODE].clk_refs == 0)
		spdif_clock_enable(0, AUDIO_TX_MODE);

	spdif_save_regs(spinfo->base);
	audio_switch_suspend();

	spdif_clock_disable(0, AUDIO_TX_MODE);

	return 0;
}
int spdif_close(int ifc)
{
	SPDIF_DEBUG_PRINT(" %s\n", __func__);

	if (!spinfo)
		return -ENOENT;
	spinfo->refcnt--;

	if (spinfo->refcnt == 0) {
		if (spinfo->spclk.spdifout_clk)
			clk_put(spinfo->spclk.spdifout_clk);

		if (spinfo->spclk.spdifin_clk)
			clk_put(spinfo->spclk.spdifin_clk);

		if (spinfo->spclk.hda2codec_clk)
			clk_put(spinfo->spclk.hda2codec_clk);

	}
	return 0;
}
Example #8
0
static inline u32 spdif_readl(unsigned long base, u32 reg)
{
	u32 val = readl(base + reg);
	SPDIF_DEBUG_PRINT("Spdif Read 0x%lx : %08x\n",base + reg, val);
	return val;
}
Example #9
0
static inline void spdif_writel(unsigned long base, u32 val, u32 reg)
{
	SPDIF_DEBUG_PRINT("Spdif Write 0x%lx : %08x\n",base + reg, val);
	writel(val, base + reg);
}