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