static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; int err = 0; if (mcbsp->active) { if (freq == mcbsp->in_freq) return 0; else return -EBUSY; } mcbsp->in_freq = freq; regs->srgr2 &= ~CLKSM; regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: regs->srgr2 |= CLKSM; break; case OMAP_MCBSP_SYSCLK_CLKS_FCLK: if (mcbsp_omap1()) { err = -EINVAL; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); break; case OMAP_MCBSP_SYSCLK_CLKS_EXT: if (mcbsp_omap1()) { err = 0; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PAD_SRC); break; case OMAP_MCBSP_SYSCLK_CLKX_EXT: regs->srgr2 |= CLKSM; case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; default: err = -ENODEV; } return err; }
void omap_mcbsp_free(struct omap_mcbsp *mcbsp) { void *reg_cache; if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id - 1); if (mcbsp->pdata->has_wakeup) MCBSP_WRITE(mcbsp, WAKEUPEN, 0); if (mcbsp->rx_irq) free_irq(mcbsp->rx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp); reg_cache = mcbsp->reg_cache; if (!cpu_class_is_omap1()) omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); spin_lock(&mcbsp->lock); if (mcbsp->free) dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); else mcbsp->free = true; mcbsp->reg_cache = NULL; spin_unlock(&mcbsp->lock); if (reg_cache) kfree(reg_cache); }
/* * ======== dsp_clk_enable ======== * Purpose: * Enable Clock . * */ int dsp_clk_enable(enum dsp_clk_id clk_id) { int status = 0; if (is_dsp_clk_active(dsp_clocks, clk_id)) { dev_err(bridge, "WARN: clock id %d already enabled\n", clk_id); goto out; } switch (get_clk_type(clk_id)) { case IVA2_CLK: clk_enable(iva2_clk); break; case GPT_CLK: timer[clk_id - 1] = omap_dm_timer_request_specific(DMT_ID(clk_id)); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: omap_mcbsp_set_io_type(MCBSP_ID(clk_id), OMAP_MCBSP_POLL_IO); omap_mcbsp_request(MCBSP_ID(clk_id)); omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC); break; #endif case WDT_CLK: dev_err(bridge, "ERROR: DSP requested to enable WDT3 clk\n"); break; case SSI_CLK: clk_enable(ssi.sst_fck); clk_enable(ssi.ssr_fck); clk_enable(ssi.ick); /* * The SSI module need to configured not to have the Forced * idle for master interface. If it is set to forced idle, * the SSI module is transitioning to standby thereby causing * the client in the DSP hang waiting for the SSI module to * be active after enabling the clocks */ ssi_clk_prepare(true); break; default: dev_err(bridge, "Invalid clock id for enable\n"); status = -EPERM; } if (!status) set_dsp_clk_active(&dsp_clocks, clk_id); out: return status; }
void omap_mcbsp_free(struct omap_mcbsp *mcbsp) { void *reg_cache; if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id - 1); /* Disable wakeup behavior */ if (mcbsp->pdata->has_wakeup) MCBSP_WRITE(mcbsp, WAKEUPEN, 0); /* Disable interrupt requests */ if (mcbsp->irq) MCBSP_WRITE(mcbsp, IRQEN, 0); if (mcbsp->irq) { free_irq(mcbsp->irq, (void *)mcbsp); } else { free_irq(mcbsp->rx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp); } reg_cache = mcbsp->reg_cache; /* * Select CLKS source from internal source unconditionally before * marking the McBSP port as free. * If the external clock source via MCBSP_CLKS pin has been selected the * system will refuse to enter idle if the CLKS pin source is not reset * back to internal source. */ if (!mcbsp_omap1()) omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); spin_lock(&mcbsp->lock); if (mcbsp->free) dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); else mcbsp->free = true; mcbsp->reg_cache = NULL; spin_unlock(&mcbsp->lock); if (reg_cache) kfree(reg_cache); }
/* * ======== dsp_clk_disable ======== * Purpose: * Disable the clock. * */ int dsp_clk_disable(enum dsp_clk_id clk_id) { int status = 0; if (!is_dsp_clk_active(dsp_clocks, clk_id)) { dev_err(bridge, "ERR: clock id %d already disabled\n", clk_id); goto out; } switch (get_clk_type(clk_id)) { case IVA2_CLK: clk_disable(iva2_clk); break; case GPT_CLK: omap_dm_timer_free(timer[clk_id - 1]); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PRCM_SRC); omap_mcbsp_free(MCBSP_ID(clk_id)); break; #endif case WDT_CLK: dev_err(bridge, "ERROR: DSP requested to disable WDT3 clk\n"); break; case SSI_CLK: ssi_clk_prepare(false); ssi_clk_prepare(false); clk_disable(ssi.sst_fck); clk_disable(ssi.ssr_fck); clk_disable(ssi.ick); break; default: dev_err(bridge, "Invalid clock id for disable\n"); status = -EPERM; } if (!status) set_dsp_clk_inactive(&dsp_clocks, clk_id); out: return status; }
static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int err = 0; if (mcbsp_data->active) { if (freq == mcbsp_data->in_freq) return 0; else return -EBUSY; } /* The McBSP signal muxing functions are only available on McBSP1 */ if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR || clk_id == OMAP_MCBSP_CLKR_SRC_CLKX || clk_id == OMAP_MCBSP_FSR_SRC_FSR || clk_id == OMAP_MCBSP_FSR_SRC_FSX) if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0) return -EINVAL; mcbsp_data->in_freq = freq; regs->srgr2 &= ~CLKSM; regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: regs->srgr2 |= CLKSM; break; case OMAP_MCBSP_SYSCLK_CLKS_FCLK: if (cpu_class_is_omap1()) { err = -EINVAL; break; } err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id, MCBSP_CLKS_PRCM_SRC); break; case OMAP_MCBSP_SYSCLK_CLKS_EXT: if (cpu_class_is_omap1()) { err = 0; break; } err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id, MCBSP_CLKS_PAD_SRC); break; case OMAP_MCBSP_SYSCLK_CLKX_EXT: regs->srgr2 |= CLKSM; case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; case OMAP_MCBSP_CLKR_SRC_CLKR: if (cpu_class_is_omap1()) break; omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR); break; case OMAP_MCBSP_CLKR_SRC_CLKX: if (cpu_class_is_omap1()) break; omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX); break; case OMAP_MCBSP_FSR_SRC_FSR: if (cpu_class_is_omap1()) break; omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR); break; case OMAP_MCBSP_FSR_SRC_FSX: if (cpu_class_is_omap1()) break; omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX); break; default: err = -ENODEV; } return err; }
static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; int err = 0; if (mcbsp->active) { if (freq == mcbsp->in_freq) return 0; else return -EBUSY; } mcbsp->in_freq = freq; regs->srgr2 &= ~CLKSM; regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: regs->srgr2 |= CLKSM; break; case OMAP_MCBSP_SYSCLK_CLKS_FCLK: if (mcbsp_omap1()) { err = -EINVAL; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); break; case OMAP_MCBSP_SYSCLK_CLKS_EXT: if (mcbsp_omap1()) { err = 0; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PAD_SRC); break; case OMAP_MCBSP_SYSCLK_CLKX_EXT: regs->srgr2 |= CLKSM; regs->pcr0 |= SCLKME; /* * If McBSP is master but yet the CLKX/CLKR pin drives the SRG, * disable output on those pins. This enables to inject the * reference clock through CLKX/CLKR. For this to work * set_dai_sysclk() _needs_ to be called after set_dai_fmt(). */ regs->pcr0 &= ~CLKXM; break; case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; /* Disable ouput on CLKR pin in master mode */ regs->pcr0 &= ~CLKRM; break; default: err = -ENODEV; } return err; }
static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; int err = 0; if (mcbsp->active) { if (freq == mcbsp->in_freq) return 0; else return -EBUSY; } if (clk_id == OMAP_MCBSP_SYSCLK_CLK || clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { mcbsp->in_freq = freq; regs->srgr2 &= ~CLKSM; regs->pcr0 &= ~SCLKME; } else if (cpu_class_is_omap1()) { /* * McBSP CLKR/FSR signal muxing functions are only available on * OMAP2 or newer versions */ return -EINVAL; } switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: regs->srgr2 |= CLKSM; break; case OMAP_MCBSP_SYSCLK_CLKS_FCLK: if (cpu_class_is_omap1()) { err = -EINVAL; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); break; case OMAP_MCBSP_SYSCLK_CLKS_EXT: if (cpu_class_is_omap1()) { err = 0; break; } err = omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PAD_SRC); break; case OMAP_MCBSP_SYSCLK_CLKX_EXT: regs->srgr2 |= CLKSM; case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; case OMAP_MCBSP_CLKR_SRC_CLKR: err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); break; case OMAP_MCBSP_CLKR_SRC_CLKX: err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); break; case OMAP_MCBSP_FSR_SRC_FSR: err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); break; case OMAP_MCBSP_FSR_SRC_FSX: err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); break; default: err = -ENODEV; } return err; }