コード例 #1
0
static int dynamic_chain_transfer(struct chain_transfer *ct)
{
	int error;
	struct dma_chain *chain_params = &(ct->chain);
	struct dma_transfer *transfer = (struct dma_transfer *)&ct->transfers;
	transfer->finished = 0;
	transfer->data_correct = 0;
	transfer->frame_count = 1;
	transfer->request_success = 0;

	switch (chain_params->data_type) {
	case OMAP_DMA_DATA_TYPE_S8:
		transfer->elements_in_frame = transfer->buffers.buf_size;
		break;
	case OMAP_DMA_DATA_TYPE_S16:
		transfer->elements_in_frame = transfer->buffers.buf_size / 2;
		break;
	case OMAP_DMA_DATA_TYPE_S32:
		transfer->elements_in_frame = transfer->buffers.buf_size / 4;
		break;
	default:
		printk(KERN_ERR "Invalid transfer data type\n");
		return 0;
	}

	map_to_phys_buffers(&transfer->buffers);
	printk(KERN_DEBUG "Chaining a transfer to chain id %d\n", chain_params->chain_id);
	transfer->chained_id = chained_id++;
	transfer->chain_id = chain_params->chain_id;
	error = omap_dma_chain_a_transfer(chain_params->chain_id,
					transfer->buffers.src_buf_phys,
					transfer->buffers.dest_buf_phys,
					transfer->elements_in_frame,
					transfer->frame_count, (void *)transfer);
	if (error) {
		printk(KERN_ERR "Error chaining transfer to chain id %d\n",
				chain_params->chain_id);
		return 1;
	}
	transfer->request_success = 1;
	printk(KERN_DEBUG " Chained transfer id is %d\n", transfer->chained_id);
	return 0;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: mcbsp.c プロジェクト: kpykc/ARDrone2.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;
}