Esempio n. 1
0
/*
 * Stop receving data on a McBSP interface
 * id		: McBSP interface ID
 */
int omap2_mcbsp_stop_datarx(u32 id)
{
	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
	void __iomem *io_base;

	if (!omap_mcbsp_check_valid_id(id)) {
		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
		return -ENODEV;
	}

	io_base = mcbsp->io_base;

	if (mcbsp->dma_rx_lch != -1) {
		if (omap_stop_dma_chain_transfers(mcbsp->dma_rx_lch) != 0)
			return -EINVAL;
	}
	OMAP_MCBSP_WRITE(mcbsp, SPCR1,
		OMAP_MCBSP_READ(mcbsp, SPCR1) & (~RRST));

	mcbsp->rx_dma_chain_state = 0;
	if (!mcbsp->tx_dma_chain_state)
		omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_DISABLE_FSG_SRG);

	return 0;
}
Esempio n. 2
0
/*
 * Reset Receiver
 * id		: McBSP interface number
 * state	: Disable (0)/ Enable (1) the receiver
 */
int omap2_mcbsp_set_rrst(unsigned int id, u8 state)
{
	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
	void __iomem *io_base;

	if (!omap_mcbsp_check_valid_id(id)) {
		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
		return -ENODEV;
	}
	io_base = mcbsp->io_base;

	if (state == OMAP_MCBSP_RRST_DISABLE)
		OMAP_MCBSP_WRITE(mcbsp, SPCR1,
			OMAP_MCBSP_READ(mcbsp, SPCR1) & (~RRST));
	else
		OMAP_MCBSP_WRITE(mcbsp, SPCR1,
			OMAP_MCBSP_READ(mcbsp, SPCR1) | RRST);
	udelay(10);
	return 0;
}
Esempio n. 3
0
/*
 * Enable/Disable the sample rate generator
 * id		: McBSP interface ID
 * state	: Enable/Disable
 */
void omap2_mcbsp_set_srg_fsg(unsigned int id, u8 state)
{
	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
	void __iomem *io_base;

	io_base = mcbsp->io_base;

	if (state == OMAP_MCBSP_DISABLE_FSG_SRG) {
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) & (~GRST));
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) & (~FRST));
	} else {
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) | GRST);
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) | FRST);
	}
	return;
}
Esempio n. 4
0
static void omap2_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
{
	struct omap_mcbsp *mcbsp_dma_tx = data;
	 void __iomem *io_base;
	io_base = mcbsp_dma_tx->io_base;

	/* If we are at the last transfer, Shut down the Transmitter */
	if ((mcbsp_dma_tx->auto_reset & OMAP_MCBSP_AUTO_XRST)
		&& (omap_dma_chain_status(mcbsp_dma_tx->dma_tx_lch) ==
						 OMAP_DMA_CHAIN_INACTIVE))
		OMAP_MCBSP_WRITE(mcbsp_dma_tx, SPCR2,
			OMAP_MCBSP_READ(mcbsp_dma_tx, SPCR2) & (~XRST));

	if (mcbsp_dma_tx->tx_callback != NULL)
		mcbsp_dma_tx->tx_callback(ch_status, mcbsp_dma_tx->tx_cb_arg);
}
Esempio n. 5
0
void omap2_mcbsp_set_srg_cfg_param(unsigned int id, int interface_mode,
					struct omap_mcbsp_reg_cfg *mcbsp_cfg,
					struct omap_mcbsp_srg_fsg_cfg *param)
{
	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
	void __iomem *io_base;
	u32 clk_rate, clkgdv;
	io_base = mcbsp->io_base;

	mcbsp->interface_mode = interface_mode;
	mcbsp_cfg->srgr1 = FWID(param->pulse_width);

	if (interface_mode == OMAP_MCBSP_MASTER) {
		clk_rate = clk_get_rate(mcbsp->fclk);
		clkgdv = clk_rate / (param->sample_rate *
				(param->bits_per_sample - 1));
		if (clkgdv > 0xFF)
			clkgdv = 0xFF;
		mcbsp_cfg->srgr1 = mcbsp_cfg->srgr1 | CLKGDV(clkgdv);
	}

	if (param->dlb)
		mcbsp_cfg->spcr1 = mcbsp_cfg->spcr1 & ~(ALB);

	if (param->sync_mode == OMAP_MCBSP_SRG_FREERUNNING)
		mcbsp_cfg->spcr2 = mcbsp_cfg->spcr2 | FREE;
	mcbsp_cfg->srgr2 = FPER(param->period)|(param->fsgm? FSGM : 0);

	switch (param->srg_src) {

	case OMAP_MCBSP_SRGCLKSRC_CLKS:
		mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(SCLKME);
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(CLKSM);
		/*
		* McBSP master operation at low voltage is only possible if
		* CLKSP=0 In Master mode, if client driver tries to configiure
		* input clock polarity as falling edge, we force it to Rising
		*/

		if ((param->polarity == OMAP_MCBSP_CLKS_POLARITY_RISING) ||
				       (interface_mode == OMAP_MCBSP_MASTER))
			mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2  & ~(CLKSP);
		else
			mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2  |  (CLKSP);
		break;


	case OMAP_MCBSP_SRGCLKSRC_FCLK:
		mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 & ~(SCLKME);
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (CLKSM);

		break;

	case OMAP_MCBSP_SRGCLKSRC_CLKR:
		mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0   | (SCLKME);
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(CLKSM);
		if (param->polarity == OMAP_MCBSP_CLKR_POLARITY_FALLING)
			mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0  & ~(CLKRP);
		else
			mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0  | (CLKRP);

		break;

	case OMAP_MCBSP_SRGCLKSRC_CLKX:
		mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0   | (SCLKME);
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (CLKSM);

		if (param->polarity == OMAP_MCBSP_CLKX_POLARITY_RISING)
			mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0  & ~(CLKXP);
		else
			mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0  | (CLKXP);
		break;

	}
	if (param->sync_mode == OMAP_MCBSP_SRG_FREERUNNING)
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 & ~(GSYNC);
	else if (param->sync_mode == OMAP_MCBSP_SRG_RUNNING)
		mcbsp_cfg->srgr2 = mcbsp_cfg->srgr2 | (GSYNC);

	mcbsp_cfg->xccr = OMAP_MCBSP_READ(mcbsp, XCCR) & ~(XDISABLE);
	if (param->dlb)
		mcbsp_cfg->xccr = mcbsp_cfg->xccr | (DILB);
	mcbsp_cfg->rccr = OMAP_MCBSP_READ(mcbsp, RCCR) & ~(RDISABLE);

	return;
	}
Esempio n. 6
0
/*
 * Start transmitting data through a McBSP interface
 * id			: McBSP interface ID
 * cbdata		: User data to be returned with callback
 * buf_start_addr	: The source address [This should be physical address]
 * buf_size		: Buffer size
 */
int omap2_mcbsp_send_data(unsigned int id, void *cbdata,
			dma_addr_t buf_start_addr, u32 buf_size)
{
	struct omap_mcbsp *mcbsp;
	 void __iomem *io_base;
	u8 enable_tx = 0;
	int e_count = 0;
	int f_count = 0;

	if (!omap_mcbsp_check_valid_id(id)) {
		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
		return -ENODEV;
	}
	mcbsp = id_to_mcbsp_ptr(id);

	io_base = mcbsp->io_base;

	mcbsp->tx_cb_arg = cbdata;

	/* Auto RRST handling logic - disable the Reciever before 1st dma */
	if ((mcbsp->auto_reset & OMAP_MCBSP_AUTO_XRST) &&
			(omap_dma_chain_status(mcbsp->dma_tx_lch)
				== OMAP_DMA_CHAIN_INACTIVE)) {
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) & (~XRST));
		enable_tx = 1;
	}
	/*
	 * for skip_first and second, we need to set e_count =2, and
	 * f_count = number of frames = number of elements/e_count
	 */
	e_count = (buf_size / mcbsp->tx_word_length);
	if (mcbsp->txskip_alt != OMAP_MCBSP_SKIP_NONE) {
		/*
		 * number of frames = total number of elements/element count,
		 * However, with double indexing for data transfers, double I
		 * the number of elements need to be transmitted
		 */
		f_count = e_count;
		e_count = 2;
	} else {
		f_count = 1;
	}

	/*
	 * If the DMA is to be configured to skip the first byte, we need
	 * to jump backwards, so we need to move one chunk forward and ask
	 * dma if we dont want the client driver knowing abt this.
	 */
	if (mcbsp->txskip_alt == OMAP_MCBSP_SKIP_FIRST)
		buf_start_addr += mcbsp->tx_word_length;

	if (omap_dma_chain_a_transfer(mcbsp->dma_tx_lch,
		buf_start_addr,	mcbsp->phys_base + OMAP_MCBSP_REG_DXR,
		e_count, f_count, mcbsp) < 0)
			return -EINVAL;

	if (mcbsp->tx_dma_chain_state == 0) {
		if (mcbsp->interface_mode == OMAP_MCBSP_MASTER)
			omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_ENABLE_FSG_SRG);

		if (omap_start_dma_chain_transfers(mcbsp->dma_tx_lch) < 0)
			return -EINVAL;
		mcbsp->tx_dma_chain_state = 1;
	}

	/* Auto XRST handling logic - Enable the Reciever after 1st dma */
	if (enable_tx &&
		(omap_dma_chain_status(mcbsp->dma_tx_lch)
		== OMAP_DMA_CHAIN_ACTIVE))
		OMAP_MCBSP_WRITE(mcbsp, SPCR2,
			OMAP_MCBSP_READ(mcbsp, SPCR2) | XRST);

	return 0;
}
Esempio n. 7
0
int omap2_mcbsp_receive_data(unsigned int id, void *cbdata,
			dma_addr_t buf_start_addr, u32 buf_size)
{
	struct omap_mcbsp *mcbsp;
	void __iomem *io_base;
	int enable_rx = 0;
	int e_count = 0;
	int f_count = 0;
	if (!omap_mcbsp_check_valid_id(id)) {
		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
		return -ENODEV;
	}

	mcbsp = id_to_mcbsp_ptr(id);

	io_base = mcbsp->io_base;
	mcbsp->rx_cb_arg = cbdata;

	/* Auto RRST handling logic - disable the Reciever before 1st dma */
	if ((mcbsp->auto_reset & OMAP_MCBSP_AUTO_RRST) &&
		(omap_dma_chain_status(mcbsp->dma_rx_lch)
				== OMAP_DMA_CHAIN_INACTIVE)) {
	OMAP_MCBSP_WRITE(io_base, SPCR1,
			OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST));
		enable_rx = 1;
	}

	/*
	 * for skip_first and second, we need to set e_count =2,
	 * and f_count = number of frames = number of elements/e_count
	 */
	e_count = (buf_size / mcbsp->rx_word_length);

	if (mcbsp->rxskip_alt != OMAP_MCBSP_SKIP_NONE) {
		/*
		 * since the number of frames = total number of elements/element
		 * count, However, with double indexing for data transfers,
		 * double the number of elements need to be transmitted
		 */
		f_count = e_count;
		e_count = 2;
	} else {
		f_count = 1;
	}
	/*
	 * If the DMA is to be configured to skip the first byte, we need
	 * to jump backwards, so we need to move one chunk forward and
	 * ask dma if we dont want the client driver knowing abt this.
	 */
	if (mcbsp->rxskip_alt == OMAP_MCBSP_SKIP_FIRST)
		buf_start_addr += mcbsp->rx_word_length;

	if (omap_dma_chain_a_transfer(mcbsp->dma_rx_lch,
			mcbsp->phys_base + OMAP_MCBSP_REG_DRR, buf_start_addr,
			e_count, f_count, mcbsp) < 0) {
		printk(KERN_ERR " Buffer chaining failed \n");
		return -EINVAL;
	}
	if (mcbsp->rx_dma_chain_state == 0) {
		if (omap_start_dma_chain_transfers(mcbsp->dma_rx_lch) < 0)
			return -EINVAL;
		mcbsp->rx_dma_chain_state = 1;
	}
	/* Auto RRST handling logic - Enable the Reciever after 1st dma */
	if (enable_rx &&
		(omap_dma_chain_status(mcbsp->dma_rx_lch)
				== OMAP_DMA_CHAIN_ACTIVE))
		OMAP_MCBSP_WRITE(io_base, SPCR1,
			OMAP_MCBSP_READ(io_base, SPCR1) | RRST);

	return 0;
}