示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
/*
 *  ======== 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;
}
示例#4
0
文件: mcbsp.c 项目: 3null/linux
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);
}
示例#5
0
/*
 *  ======== 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;
}
示例#6
0
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;
}
示例#7
0
文件: omap-mcbsp.c 项目: 020gzh/linux
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;
}
示例#8
0
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;
}