public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2]  McBSP DMA support for  34xx
@ 2008-08-28  8:26 chandra shekhar
  2008-08-28 10:10 ` Felipe Balbi
  2008-08-28 10:52 ` Jarkko Nikula
  0 siblings, 2 replies; 9+ messages in thread
From: chandra shekhar @ 2008-08-28  8:26 UTC (permalink / raw)
  To: linux-omap

This patch supports DMA chaining mode and one time configuration for entire
transfer to improve performance.
Signed-off-by: chandra shekhar <x0044955@ti.com>
---
 arch/arm/mach-omap2/mcbsp.c       |  702 +++++++++++++++++++++++++++++++++++++-
 arch/arm/plat-omap/mcbsp.c        |   19 -
 include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
 3 files changed, 811 insertions(+), 37 deletions(-)

Index: linux-omap-2.6/arch/arm/mach-omap2/mcbsp.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/mcbsp.c	2008-08-26
19:13:47.000000000 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/mcbsp.c	2008-08-26 19:56:39.000000000 +0530
@@ -16,6 +16,8 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>

 #include <asm/arch/dma.h>
 #include <asm/arch/mux.h>
@@ -91,7 +93,7 @@
 	},
 	{
 		.clk = {
-			.name		= "mcbsp_clk",
+			.name 		= "mcbsp_clk",
 			.id		= 3,
 			.enable		= omap_mcbsp_clk_enable,
 			.disable	= omap_mcbsp_clk_disable,
@@ -99,7 +101,7 @@
 	},
 	{
 		.clk = {
-			.name		= "mcbsp_clk",
+			.name 		= "mcbsp_clk",
 			.id		= 4,
 			.enable		= omap_mcbsp_clk_enable,
 			.disable	= omap_mcbsp_clk_disable,
@@ -107,7 +109,7 @@
 	},
 	{
 		.clk = {
-			.name		= "mcbsp_clk",
+			.name 		= "mcbsp_clk",
 			.id		= 5,
 			.enable		= omap_mcbsp_clk_enable,
 			.disable	= omap_mcbsp_clk_disable,
@@ -139,11 +141,700 @@
 {
 	if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
 		omap2_mcbsp2_mux_setup();
+	else
+		omap2_mcbsp_reset(id);
 }

+static void omap2_mcbsp_free(unsigned int id)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+
+	if (!cpu_is_omap2420()) {
+		if (mcbsp->dma_rx_lch != -1) {
+			omap_free_dma_chain(mcbsp->dma_rx_lch);
+			 mcbsp->dma_rx_lch = -1;
+		}
+
+		if (mcbsp->dma_tx_lch != -1) {
+			omap_free_dma_chain(mcbsp->dma_tx_lch);
+			mcbsp->dma_tx_lch = -1;
+		}
+	}
+	return;
+}
+void omap2_mcbsp_config(unsigned int id,
+			 const struct omap_mcbsp_reg_cfg *config)
+{
+	struct omap_mcbsp *mcbsp;
+	u32 io_base;
+	mcbsp = id_to_mcbsp_ptr(id);
+	io_base = mcbsp->io_base;
+	OMAP_MCBSP_WRITE(io_base, XCCR, config->xccr);
+	OMAP_MCBSP_WRITE(io_base, RCCR, config->rccr);
+}
 static struct omap_mcbsp_ops omap2_mcbsp_ops = {
 	.request	= omap2_mcbsp_request,
+	.free 		= omap2_mcbsp_free,
+	.config		= omap2_mcbsp_config,
 };
+static void omap2_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct omap_mcbsp *mcbsp_dma_rx = data;
+	u32 io_base;
+	io_base = mcbsp_dma_rx->io_base;
+
+	/* If we are at the last transfer, Shut down the reciever */
+	if ((mcbsp_dma_rx->auto_reset & OMAP_MCBSP_AUTO_RRST)
+		&& (omap_dma_chain_status(mcbsp_dma_rx->dma_rx_lch) ==
+						 OMAP_DMA_CHAIN_INACTIVE))
+		OMAP_MCBSP_WRITE(io_base, SPCR1,
+			OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST));
+
+	if (mcbsp_dma_rx->rx_callback != NULL)
+		mcbsp_dma_rx->rx_callback(ch_status, mcbsp_dma_rx->rx_cb_arg);
+
+}
+
+static void omap2_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct omap_mcbsp *mcbsp_dma_tx = data;
+	u32 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(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
+
+	if (mcbsp_dma_tx->tx_callback != NULL)
+		mcbsp_dma_tx->tx_callback(ch_status, mcbsp_dma_tx->tx_cb_arg);
+}
+
+/*
+ * 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];
+	u32 io_base;
+
+	io_base = mcbsp->io_base;
+
+	if (state == OMAP_MCBSP_DISABLE_FSG_SRG) {
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) & (~GRST));
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) & (~FRST));
+	} else {
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) | GRST);
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) | FRST);
+	}
+	return;
+}
+
+/*
+ * Stop transmitting data on a McBSP interface
+ * id		: McBSP interface ID
+ */
+int omap2_mcbsp_stop_datatx(unsigned int id)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+	u32 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_tx_lch != -1) {
+		if (omap_stop_dma_chain_transfers(mcbsp->dma_tx_lch) != 0)
+			return -EINVAL;
+	}
+	mcbsp->tx_dma_chain_state = 0;
+	OMAP_MCBSP_WRITE(io_base, SPCR2,
+		OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
+
+	if (!mcbsp->rx_dma_chain_state)
+		omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_DISABLE_FSG_SRG);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_stop_datatx);
+
+/*
+ * 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];
+	u32 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(io_base, SPCR1,
+		OMAP_MCBSP_READ(io_base, 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;
+}
+EXPORT_SYMBOL(omap2_mcbsp_stop_datarx);
+
+/*
+ * Interface Reset
+ * id	: McBSP interface ID
+ * Resets the McBSP interface
+ */
+int omap2_mcbsp_reset(unsigned int id)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+	u32 io_base;
+	int counter = 0;
+	int wait_for_reset = 10000;
+
+	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;
+
+	OMAP_MCBSP_WRITE(io_base, SYSCON,
+		OMAP_MCBSP_READ(io_base, SYSCON) | (SOFTRST));
+
+	while (OMAP_MCBSP_READ(io_base, SYSCON) & SOFTRST) {
+		if (!in_interrupt()) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(10);
+		}
+		if (counter++ > wait_for_reset) {
+			printk(KERN_ERR "mcbsp[%d] Reset timeout\n", id);
+			return -ETIMEDOUT;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_reset);
+
+/*
+ * Get the element index and frame index of transmitter
+ * id		: McBSP interface ID
+ * ei		: element index
+ * fi		: frame index
+ */
+int omap2_mcbsp_transmitter_index(int id, int *ei, int *fi)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+	int eix = 0, fix = 0;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+
+	if ((!ei) || (!fi)) {
+		printk(KERN_ERR	"OMAP_McBSP: Invalid ei and fi params \n");
+		goto txinx_err;
+	}
+
+	if (mcbsp->dma_tx_lch == -1) {
+		printk(KERN_ERR "OMAP_McBSP: Transmitter not started\n");
+		goto txinx_err;
+	}
+
+	if (omap_get_dma_chain_index
+		(mcbsp->dma_tx_lch, &eix, &fix) != 0) {
+		printk(KERN_ERR "OMAP_McBSP: Getting chain index failed\n");
+		goto txinx_err;
+	}
+
+	*ei = eix;
+	*fi = fix;
+
+	return 0;
+
+txinx_err:
+	return -EINVAL;
+}
+EXPORT_SYMBOL(omap2_mcbsp_transmitter_index);
+
+/*
+ * Get the element index and frame index of receiver
+ * id	: McBSP interface ID
+ * ei		: element index
+ * fi		: frame index
+ */
+int omap2_mcbsp_receiver_index(int id, int *ei, int *fi)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+	int eix = 0, fix = 0;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+
+	if ((!ei) || (!fi)) {
+		printk(KERN_ERR	"OMAP_McBSP: Invalid ei and fi params x\n");
+		goto rxinx_err;
+	}
+
+	/* Check if chain exists */
+	if (mcbsp->dma_rx_lch == -1) {
+		printk(KERN_ERR "OMAP_McBSP: Receiver not started\n");
+		goto rxinx_err;
+	}
+
+	/* Get dma_chain_index */
+	if (omap_get_dma_chain_index
+		(mcbsp->dma_rx_lch, &eix, &fix) != 0) {
+		printk(KERN_ERR "OMAP_McBSP: Getting chain index failed\n");
+		goto rxinx_err;
+	}
+
+	*ei = eix;
+	*fi = fix;
+	return 0;
+
+rxinx_err:
+	return -EINVAL;
+}
+EXPORT_SYMBOL(omap2_mcbsp_receiver_index);
+
+/*
+ * Basic Reset Transmitter
+ * id		: McBSP interface number
+ * state	: Disable (0)/ Enable (1) the transmitter
+ */
+int omap2_mcbsp_set_xrst(unsigned int id, u8 state)
+{
+	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
+	u32 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_XRST_DISABLE)
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+		      OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
+	else
+		OMAP_MCBSP_WRITE(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) | XRST);
+	udelay(10);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_set_xrst);
+
+/*
+ * 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];
+	u32 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(io_base, SPCR1,
+			OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST));
+	else
+		OMAP_MCBSP_WRITE(io_base, SPCR1,
+		      OMAP_MCBSP_READ(io_base, SPCR1) | RRST);
+	udelay(10);
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_set_rrst);
+
+/*
+ * Configure the receiver parameters
+ * id		: McBSP Interface ID
+ * rp		: DMA Receive parameters
+ */
+int omap2_mcbsp_dma_recv_params(unsigned int id,
+			struct omap_mcbsp_dma_transfer_params *rp)
+{
+	struct omap_mcbsp *mcbsp;
+	u32 io_base;
+	int err, chain_id = -1;
+	struct omap_dma_channel_params rx_params;
+	u32  dt = 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;
+	dt = rp->word_length1;
+
+	if (dt == OMAP_MCBSP_WORD_8)
+		rx_params.data_type = OMAP_DMA_DATA_TYPE_S8;
+	else if (dt == OMAP_MCBSP_WORD_16)
+		rx_params.data_type = OMAP_DMA_DATA_TYPE_S16;
+	else if (dt == OMAP_MCBSP_WORD_32)
+		rx_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+	else
+		return -EINVAL;
+
+	rx_params.read_prio = DMA_CH_PRIO_HIGH;
+	rx_params.write_prio = DMA_CH_PRIO_HIGH;
+	rx_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
+	rx_params.src_fi = 0;
+	rx_params.trigger = mcbsp->dma_rx_sync;
+	rx_params.src_or_dst_synch = 0x01;
+	rx_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
+	rx_params.src_ei = 0x0;
+	/* Indexing is always in bytes - so multiply with dt */
+
+	dt = (rx_params.data_type == OMAP_DMA_DATA_TYPE_S8) ? 1 :
+		(rx_params.data_type == OMAP_DMA_DATA_TYPE_S16) ? 2 : 4;
+
+	/* SKIP_FIRST and SKIP_SECOND- skip alternate data in 24 bit mono */
+	if (rp->skip_alt == OMAP_MCBSP_SKIP_SECOND) {
+		rx_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
+		rx_params.dst_ei = (1);
+		rx_params.dst_fi = (1) + ((-1) * dt);
+	} else if (rp->skip_alt == OMAP_MCBSP_SKIP_FIRST) {
+		rx_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
+		rx_params.dst_ei = 1 + (-2) * dt;
+		rx_params.dst_fi = 1 + (2) * dt;
+	} else {
+		rx_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
+		rx_params.dst_ei = 0;
+		rx_params.dst_fi = 0;
+	}
+
+	mcbsp->rxskip_alt = rp->skip_alt;
+	mcbsp->auto_reset &= ~OMAP_MCBSP_AUTO_RRST;
+	mcbsp->auto_reset |=	(rp->auto_reset & OMAP_MCBSP_AUTO_RRST);
+
+	mcbsp->rx_word_length = rx_params.data_type << 0x1;
+	if (rx_params.data_type == 0)
+		mcbsp->rx_word_length = 1;
+
+	mcbsp->rx_callback = rp->callback;
+	/* request for a chain of dma channels for data reception */
+	if (mcbsp->dma_rx_lch == -1) {
+		err = omap_request_dma_chain(id, "McBSP RX",
+					 omap2_mcbsp_rx_dma_callback, &chain_id,
+					 2, OMAP_DMA_DYNAMIC_CHAIN, rx_params);
+		if (err < 0) {
+			printk(KERN_ERR "Receive path configuration failed \n");
+			return -EINVAL;
+		}
+		mcbsp->dma_rx_lch = chain_id;
+		mcbsp->rx_dma_chain_state = 0;
+	} else {
+		/* DMA params already set, modify the same!! */
+		err = omap_modify_dma_chain_params(mcbsp->dma_rx_lch,
+								 rx_params);
+		if (err < 0)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_dma_recv_params);
+
+/*
+ * Configure the transmitter parameters
+ * id		: McBSP Interface ID
+ * tp		: DMA Transfer parameters
+ */
+
+int omap2_mcbsp_dma_trans_params(unsigned int id,
+			struct omap_mcbsp_dma_transfer_params *tp)
+{
+	struct omap_mcbsp *mcbsp;
+
+	struct omap_dma_channel_params tx_params;
+	int err = 0, chain_id = -1;
+	u32 io_base;
+	u32 dt = 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;
+
+	dt = tp->word_length1;
+	if ((dt != OMAP_MCBSP_WORD_8) && (dt != OMAP_MCBSP_WORD_16)
+						 && (dt != OMAP_MCBSP_WORD_32))
+		return -EINVAL;
+	if (dt == OMAP_MCBSP_WORD_8)
+		tx_params.data_type = OMAP_DMA_DATA_TYPE_S8;
+	else if (dt == OMAP_MCBSP_WORD_16)
+		tx_params.data_type = OMAP_DMA_DATA_TYPE_S16;
+	else if (dt == OMAP_MCBSP_WORD_32)
+		tx_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+	else
+		return -EINVAL;
+
+	tx_params.read_prio = DMA_CH_PRIO_HIGH;
+	tx_params.write_prio = DMA_CH_PRIO_HIGH;
+	tx_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
+	tx_params.dst_fi = 0;
+	tx_params.trigger = mcbsp->dma_tx_sync;
+	tx_params.src_or_dst_synch = 0;
+	tx_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
+	tx_params.dst_ei = 0;
+	/* Indexing is always in bytes - so multiply with dt */
+	mcbsp->tx_word_length = tx_params.data_type << 0x1;
+
+	if (tx_params.data_type == 0)
+		mcbsp->tx_word_length = 1;
+	dt = mcbsp->tx_word_length;
+
+	/* SKIP_FIRST and SKIP_SECOND- skip alternate data in 24 bit mono */
+	if (tp->skip_alt == OMAP_MCBSP_SKIP_SECOND) {
+		tx_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
+		tx_params.src_ei = (1);
+		tx_params.src_fi = (1) + ((-1) * dt);
+	} else if (tp->skip_alt == OMAP_MCBSP_SKIP_FIRST) {
+		tx_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
+		tx_params.src_ei = 1 + (-2) * dt;
+		tx_params.src_fi = 1 + (2) * dt;
+	} else {
+		tx_params.src_amode = OMAP_DMA_AMODE_POST_INC;
+		tx_params.src_ei = 0;
+		tx_params.src_fi = 0;
+	}
+
+	mcbsp->txskip_alt = tp->skip_alt;
+	mcbsp->auto_reset &= ~OMAP_MCBSP_AUTO_XRST;
+	mcbsp->auto_reset |=
+		(tp->auto_reset & OMAP_MCBSP_AUTO_XRST);
+	mcbsp->tx_callback = tp->callback;
+
+	/* Based on Rjust we can do double indexing DMA params configuration */
+	if (mcbsp->dma_tx_lch == -1) {
+		err = omap_request_dma_chain(id, "McBSP TX",
+					 omap2_mcbsp_tx_dma_callback, &chain_id,
+					 2, OMAP_DMA_DYNAMIC_CHAIN, tx_params);
+		if (err < 0) {
+			printk(KERN_ERR
+				"Transmit path configuration failed \n");
+			return -EINVAL;
+		}
+		mcbsp->tx_dma_chain_state = 0;
+	mcbsp->dma_tx_lch = chain_id;
+	} else {
+		/* DMA params already set, modify the same!! */
+		err = omap_modify_dma_chain_params(mcbsp->dma_tx_lch,
+								 tx_params);
+		if (err < 0)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_dma_trans_params);
+
+/*
+ * Start receving data on a McBSP interface
+ * id			: McBSP interface ID
+ * cbdata		: User data to be returned with callback
+ * buf_start_addr	: The destination address [physical address]
+ * buf_size		: Buffer size
+ */
+
+int omap2_mcbsp_receive_data(unsigned int id, void *cbdata,
+			     dma_addr_t buf_start_addr, u32 buf_size)
+{
+	struct omap_mcbsp *mcbsp;
+	u32 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->phy_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 (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_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;
+}
+EXPORT_SYMBOL(omap2_mcbsp_receive_data);
+
+/*
+ * 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;
+	u32 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(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, 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->phy_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(io_base, SPCR2,
+			OMAP_MCBSP_READ(io_base, SPCR2) | XRST);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_send_data);

 #ifdef CONFIG_ARCH_OMAP24XX
 static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
@@ -176,6 +867,7 @@
 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
 	{
 		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
+		.phy_base	= OMAP34XX_MCBSP1_BASE,
 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
@@ -185,6 +877,7 @@
 	},
 	{
 		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
+		.phy_base	= OMAP34XX_MCBSP2_BASE,
 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
@@ -194,6 +887,7 @@
 	},
 	{
 		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP3_BASE),
+		.phy_base	= OMAP34XX_MCBSP3_BASE,
 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
 		.ops		= &omap2_mcbsp_ops,
@@ -201,6 +895,7 @@
 	},
 	{
 		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP4_BASE),
+		.phy_base	= OMAP34XX_MCBSP4_BASE,
 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
 		.ops		= &omap2_mcbsp_ops,
@@ -208,6 +903,7 @@
 	},
 	{
 		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP5_BASE),
+		.phy_base	= OMAP34XX_MCBSP5_BASE,
 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
 		.ops		= &omap2_mcbsp_ops,
Index: linux-omap-2.6/arch/arm/plat-omap/mcbsp.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/plat-omap/mcbsp.c	2008-08-26
19:13:47.000000000 +0530
+++ linux-omap-2.6/arch/arm/plat-omap/mcbsp.c	2008-08-26 19:55:24.000000000 +0530
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/irq.h>

 #include <asm/arch/dma.h>
 #include <asm/arch/mcbsp.h>
@@ -46,14 +47,6 @@
 		return __raw_readl(io_base + reg);
 }

-#define OMAP_MCBSP_READ(base, reg) \
-			omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
-#define OMAP_MCBSP_WRITE(base, reg, val) \
-			omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val)
-
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
-
 static void omap_mcbsp_dump_reg(u8 id)
 {
 	struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
@@ -173,6 +166,11 @@
 	OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
 	OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
 	OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
+	if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+		if (mcbsp->pdata->ops->config)
+			mcbsp->pdata->ops->config(id, config);
+	}
+
 }
 EXPORT_SYMBOL(omap_mcbsp_config);

@@ -218,11 +216,11 @@
 	}
 	mcbsp = id_to_mcbsp_ptr(id);

+	clk_enable(mcbsp->clk);
+
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
 		mcbsp->pdata->ops->request(id);

-	clk_enable(mcbsp->clk);
-
 	spin_lock(&mcbsp->lock);
 	if (!mcbsp->free) {
 		dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
@@ -893,6 +891,7 @@
 	mcbsp->dma_rx_lch = -1;

 	mcbsp->io_base = pdata->virt_base;
+	mcbsp->phy_base = pdata->phy_base;
 	/* Default I/O is IRQ based */
 	mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
 	mcbsp->tx_irq = pdata->tx_irq;
Index: linux-omap-2.6/include/asm-arm/arch-omap/mcbsp.h
===================================================================
--- linux-omap-2.6.orig/include/asm-arm/arch-omap/mcbsp.h	2008-08-26
19:13:47.000000000 +0530
+++ linux-omap-2.6/include/asm-arm/arch-omap/mcbsp.h	2008-08-26
19:55:42.000000000 +0530
@@ -239,31 +239,58 @@
 /********************** McBSP SYSCONFIG bit definitions ********************/
 #define SOFTRST			0x0002

+/********************** MACRO DEFINITIONS *********************************/
+
+/* McBSP interface operating mode */
+#define OMAP_MCBSP_MASTER			1
+#define OMAP_MCBSP_SLAVE			0
+
+#define OMAP_MCBSP_AUTO_RST_NONE		(0x0)
+#define OMAP_MCBSP_AUTO_RRST			(0x1<<1)
+#define OMAP_MCBSP_AUTO_XRST			(0x1<<2)
+
+/* SRG ENABLE/DISABLE state */
+#define OMAP_MCBSP_ENABLE_FSG_SRG		1
+#define OMAP_MCBSP_DISABLE_FSG_SRG		0
+/* mono to mono mode*/
+#define OMAP_MCBSP_SKIP_NONE			(0x0)
+/* mono to stereo mode */
+#define OMAP_MCBSP_SKIP_FIRST			(0x1<<1)
+#define OMAP_MCBSP_SKIP_SECOND			(0x1<<2)
+/* RRST STATE */
+#define OMAP_MCBSP_RRST_DISABLE			0
+#define OMAP_MCBSP_RRST_ENABLE			1
+/*XRST STATE */
+#define OMAP_MCBSP_XRST_DISABLE			0
+#define OMAP_MCBSP_XRST_ENABLE			1
+
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
-	u16 spcr2;
-	u16 spcr1;
-	u16 rcr2;
-	u16 rcr1;
-	u16 xcr2;
-	u16 xcr1;
-	u16 srgr2;
-	u16 srgr1;
-	u16 mcr2;
-	u16 mcr1;
-	u16 pcr0;
-	u16 rcerc;
-	u16 rcerd;
-	u16 xcerc;
-	u16 xcerd;
-	u16 rcere;
-	u16 rcerf;
-	u16 xcere;
-	u16 xcerf;
-	u16 rcerg;
-	u16 rcerh;
-	u16 xcerg;
-	u16 xcerh;
+	u32 spcr2;
+	u32 spcr1;
+	u32 rcr2;
+	u32 rcr1;
+	u32 xcr2;
+	u32 xcr1;
+	u32 srgr2;
+	u32 srgr1;
+	u32 mcr2;
+	u32 mcr1;
+	u32 pcr0;
+	u32 rcerc;
+	u32 rcerd;
+	u32 xcerc;
+	u32 xcerd;
+	u32 rcere;
+	u32 rcerf;
+	u32 xcere;
+	u32 xcerf;
+	u32 rcerg;
+	u32 rcerh;
+	u32 xcerg;
+	u32 xcerh;
+	u32 xccr;
+	u32 rccr;
 };

 typedef enum {
@@ -277,6 +304,7 @@
 typedef int __bitwise omap_mcbsp_io_type_t;
 #define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
 #define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
+typedef void (*omap_mcbsp_dma_cb) (u32 ch_status, void *arg);

 typedef enum {
 	OMAP_MCBSP_WORD_8 = 0,
@@ -319,14 +347,28 @@
 	omap_mcbsp_word_length		word_length;
 };

+struct omap_mcbsp_dma_transfer_params {
+	/* Skip the alternate element use fro stereo mode */
+	u8 skip_alt;
+	/* Automagically handle Transfer [XR]RST? */
+	u8   auto_reset;
+	/* callback function executed for every tx/rx completion */
+	omap_mcbsp_dma_cb callback;
+	/* word length of data */
+	u32 word_length1;
+
+};
+
 /* Platform specific configuration */
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
 	void (*free)(unsigned int);
+	void (*config)(unsigned int,  const struct omap_mcbsp_reg_cfg *config);
 };

 struct omap_mcbsp_platform_data {
 	u32 virt_base;
+	u32 phy_base;
 	u8 dma_rx_sync, dma_tx_sync;
 	u16 rx_irq, tx_irq;
 	struct omap_mcbsp_ops *ops;
@@ -362,10 +404,32 @@
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
 	struct clk *clk;
+	u32 phy_base;
+	u8  auto_reset;	/* Auto Reset */
+	u8  txskip_alt;	/* Tx skip flags */
+	u8  rxskip_alt;	/* Rx skip flags */
+	void  *rx_cb_arg;
+	void  *tx_cb_arg;
+	omap_mcbsp_dma_cb  rx_callback;
+	omap_mcbsp_dma_cb  tx_callback;
+	int  rx_dma_chain_state;
+	int  tx_dma_chain_state;
+	int  interface_mode; /* Master / Slave */
 };
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count;

+#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
+
+void omap_mcbsp_write(u32 io_base, u16 reg, u32 val);
+int omap_mcbsp_read(u32 io_base, u16 reg);
+
+#define OMAP_MCBSP_READ(base, reg) \
+			omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
+#define OMAP_MCBSP_WRITE(base, reg, val) \
+			omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val)
+
 int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 					int size);
@@ -382,7 +446,6 @@
 int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
 int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);

-
 /* SPI specific API */
 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg
* spi_cfg);

@@ -391,4 +454,20 @@
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
 int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);

+int omap2_mcbsp_stop_datatx(unsigned int id);
+int omap2_mcbsp_stop_datarx(u32 id);
+int omap2_mcbsp_reset(unsigned int id);
+int omap2_mcbsp_transmitter_index(int id, int *ei, int *fi);
+int omap2_mcbsp_receiver_index(int id, int *ei, int *fi);
+int omap2_mcbsp_set_xrst(unsigned int id, u8 state);
+int omap2_mcbsp_set_rrst(unsigned int id, u8 state);
+int omap2_mcbsp_dma_recv_params(unsigned int id,
+			struct	omap_mcbsp_dma_transfer_params *rp);
+int omap2_mcbsp_dma_trans_params(unsigned int id,
+			struct	omap_mcbsp_dma_transfer_params *tp);
+int omap2_mcbsp_receive_data(unsigned int id, void *cbdata,
+				dma_addr_t buf_start_addr, u32 buf_size);
+int omap2_mcbsp_send_data(unsigned int id, void *cbdata,
+				dma_addr_t buf_start_addr, u32 buf_size);
+
 #endif



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-08-28  8:26 [PATCH 1/2] McBSP DMA support for 34xx chandra shekhar
@ 2008-08-28 10:10 ` Felipe Balbi
  2008-08-28 10:52 ` Jarkko Nikula
  1 sibling, 0 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-08-28 10:10 UTC (permalink / raw)
  To: ext chandra shekhar; +Cc: linux-omap

On Thu, Aug 28, 2008 at 01:56:00PM +0530, ext chandra shekhar wrote:
> This patch supports DMA chaining mode and one time configuration for entire
> transfer to improve performance.
> Signed-off-by: chandra shekhar <x0044955@ti.com>
> ---
>  arch/arm/mach-omap2/mcbsp.c       |  702 +++++++++++++++++++++++++++++++++++++-
>  arch/arm/plat-omap/mcbsp.c        |   19 -
>  include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
>  3 files changed, 811 insertions(+), 37 deletions(-)
> 
> Index: linux-omap-2.6/arch/arm/mach-omap2/mcbsp.c
> ===================================================================
> --- linux-omap-2.6.orig/arch/arm/mach-omap2/mcbsp.c	2008-08-26
> 19:13:47.000000000 +0530
> +++ linux-omap-2.6/arch/arm/mach-omap2/mcbsp.c	2008-08-26 19:56:39.000000000 +0530
> @@ -16,6 +16,8 @@
>  #include <linux/err.h>
>  #include <linux/io.h>
>  #include <linux/platform_device.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> 
>  #include <asm/arch/dma.h>
>  #include <asm/arch/mux.h>
> @@ -91,7 +93,7 @@
>  	},
>  	{
>  		.clk = {
> -			.name		= "mcbsp_clk",
> +			.name 		= "mcbsp_clk",
			     ^ you added whitespace there.
>  			.id		= 3,
>  			.enable		= omap_mcbsp_clk_enable,
>  			.disable	= omap_mcbsp_clk_disable,
> @@ -99,7 +101,7 @@
>  	},
>  	{
>  		.clk = {
> -			.name		= "mcbsp_clk",
> +			.name 		= "mcbsp_clk",
			     ^ you added whitespace there.
>  			.id		= 4,
>  			.enable		= omap_mcbsp_clk_enable,
>  			.disable	= omap_mcbsp_clk_disable,
> @@ -107,7 +109,7 @@
>  	},
>  	{
>  		.clk = {
> -			.name		= "mcbsp_clk",
> +			.name 		= "mcbsp_clk",
			     ^ you added whitespace there.
>  			.id		= 5,
>  			.enable		= omap_mcbsp_clk_enable,
>  			.disable	= omap_mcbsp_clk_disable,
> @@ -139,11 +141,700 @@
>  {
>  	if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
>  		omap2_mcbsp2_mux_setup();
> +	else
> +		omap2_mcbsp_reset(id);
>  }
> 
> +static void omap2_mcbsp_free(unsigned int id)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +
> +	if (!cpu_is_omap2420()) {
> +		if (mcbsp->dma_rx_lch != -1) {
> +			omap_free_dma_chain(mcbsp->dma_rx_lch);
> +			 mcbsp->dma_rx_lch = -1;
			^ extra space here
> +		}
> +
> +		if (mcbsp->dma_tx_lch != -1) {
> +			omap_free_dma_chain(mcbsp->dma_tx_lch);
> +			mcbsp->dma_tx_lch = -1;
> +		}
> +	}
> +	return;

this return is not needed.

> +}

put a blank line between function declarations

> +void omap2_mcbsp_config(unsigned int id,
> +			 const struct omap_mcbsp_reg_cfg *config)

			don't use space for identation.
> +{
> +	struct omap_mcbsp *mcbsp;
> +	u32 io_base;

a blank line after variable declarations and before the funtion body
wouldn't hurt.

> +	mcbsp = id_to_mcbsp_ptr(id);
> +	io_base = mcbsp->io_base;
> +	OMAP_MCBSP_WRITE(io_base, XCCR, config->xccr);
> +	OMAP_MCBSP_WRITE(io_base, RCCR, config->rccr);
> +}

add blank line here

>  static struct omap_mcbsp_ops omap2_mcbsp_ops = {
>  	.request	= omap2_mcbsp_request,
> +	.free 		= omap2_mcbsp_free,
	     ^ whitespace
> +	.config		= omap2_mcbsp_config,
>  };

add a blank line

> +static void omap2_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct omap_mcbsp *mcbsp_dma_rx = data;
> +	u32 io_base;
> +	io_base = mcbsp_dma_rx->io_base;
> +
> +	/* If we are at the last transfer, Shut down the reciever */
> +	if ((mcbsp_dma_rx->auto_reset & OMAP_MCBSP_AUTO_RRST)
> +		&& (omap_dma_chain_status(mcbsp_dma_rx->dma_rx_lch) ==
> +						 OMAP_DMA_CHAIN_INACTIVE))
> +		OMAP_MCBSP_WRITE(io_base, SPCR1,
> +			OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST));
> +
> +	if (mcbsp_dma_rx->rx_callback != NULL)
> +		mcbsp_dma_rx->rx_callback(ch_status, mcbsp_dma_rx->rx_cb_arg);
> +
> +}
> +
> +static void omap2_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct omap_mcbsp *mcbsp_dma_tx = data;
> +	u32 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(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
> +
> +	if (mcbsp_dma_tx->tx_callback != NULL)
> +		mcbsp_dma_tx->tx_callback(ch_status, mcbsp_dma_tx->tx_cb_arg);
> +}
> +
> +/*
> + * Enable/Disable the sample rate generator
> + * id		: McBSP interface ID
> + * state	: Enable/Disable

please follow the kernel-doc style:

/**
 * omap2_mcbsp_set_srg_fsg - enable/disable 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];
> +	u32 io_base;
> +
> +	io_base = mcbsp->io_base;
> +
> +	if (state == OMAP_MCBSP_DISABLE_FSG_SRG) {
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) & (~GRST));
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) & (~FRST));
> +	} else {
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) | GRST);
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) | FRST);
> +	}
> +	return;
> +}
> +
> +/*
> + * Stop transmitting data on a McBSP interface
> + * id		: McBSP interface ID
> + */

follow kernel-doc style

> +int omap2_mcbsp_stop_datatx(unsigned int id)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	u32 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_tx_lch != -1) {
> +		if (omap_stop_dma_chain_transfers(mcbsp->dma_tx_lch) != 0)
> +			return -EINVAL;
> +	}

add a blank line here.

> +	mcbsp->tx_dma_chain_state = 0;
> +	OMAP_MCBSP_WRITE(io_base, SPCR2,
> +		OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
> +
> +	if (!mcbsp->rx_dma_chain_state)
> +		omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_DISABLE_FSG_SRG);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_stop_datatx);
> +
> +/*
> + * Stop receving data on a McBSP interface
> + * id		: McBSP interface ID
> + */

follow kernel-doc style

> +int omap2_mcbsp_stop_datarx(u32 id)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	u32 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;
> +	}

add a blank line here

> +	OMAP_MCBSP_WRITE(io_base, SPCR1,
> +		OMAP_MCBSP_READ(io_base, 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;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_stop_datarx);
> +
> +/*
> + * Interface Reset
> + * id	: McBSP interface ID
> + * Resets the McBSP interface
> + */

follow kernel-doc style

> +int omap2_mcbsp_reset(unsigned int id)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	u32 io_base;
> +	int counter = 0;
> +	int wait_for_reset = 10000;
> +
> +	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;
> +
> +	OMAP_MCBSP_WRITE(io_base, SYSCON,
> +		OMAP_MCBSP_READ(io_base, SYSCON) | (SOFTRST));
> +
> +	while (OMAP_MCBSP_READ(io_base, SYSCON) & SOFTRST) {
> +		if (!in_interrupt()) {
> +			set_current_state(TASK_INTERRUPTIBLE);
> +			schedule_timeout(10);
> +		}
> +		if (counter++ > wait_for_reset) {
> +			printk(KERN_ERR "mcbsp[%d] Reset timeout\n", id);
> +			return -ETIMEDOUT;
> +		}
> +	}

add a blank line before return statements

> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_reset);
> +
> +/*
> + * Get the element index and frame index of transmitter
> + * id		: McBSP interface ID
> + * ei		: element index
> + * fi		: frame index
> + */

follow kernel-doc style

> +int omap2_mcbsp_transmitter_index(int id, int *ei, int *fi)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	int eix = 0, fix = 0;
> +
> +	if (!omap_mcbsp_check_valid_id(id)) {
> +		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
> +		return -ENODEV;
> +	}
> +
> +	if ((!ei) || (!fi)) {

	too many ()

> +		printk(KERN_ERR	"OMAP_McBSP: Invalid ei and fi params \n");
> +		goto txinx_err;
> +	}
> +
> +	if (mcbsp->dma_tx_lch == -1) {
> +		printk(KERN_ERR "OMAP_McBSP: Transmitter not started\n");
> +		goto txinx_err;
> +	}
> +
> +	if (omap_get_dma_chain_index
> +		(mcbsp->dma_tx_lch, &eix, &fix) != 0) {

	fits in one line

> +		printk(KERN_ERR "OMAP_McBSP: Getting chain index failed\n");
> +		goto txinx_err;
> +	}
> +
> +	*ei = eix;
> +	*fi = fix;
> +
> +	return 0;
> +
> +txinx_err:
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_transmitter_index);
> +
> +/*
> + * Get the element index and frame index of receiver
> + * id	: McBSP interface ID
> + * ei		: element index
> + * fi		: frame index
> + */

follow kernel-doc style

> +int omap2_mcbsp_receiver_index(int id, int *ei, int *fi)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	int eix = 0, fix = 0;
> +
> +	if (!omap_mcbsp_check_valid_id(id)) {
> +		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
> +		return -ENODEV;
> +	}
> +
> +	if ((!ei) || (!fi)) {

	too many ()

> +		printk(KERN_ERR	"OMAP_McBSP: Invalid ei and fi params x\n");
> +		goto rxinx_err;
> +	}
> +
> +	/* Check if chain exists */
> +	if (mcbsp->dma_rx_lch == -1) {
> +		printk(KERN_ERR "OMAP_McBSP: Receiver not started\n");
> +		goto rxinx_err;
> +	}
> +
> +	/* Get dma_chain_index */
> +	if (omap_get_dma_chain_index
> +		(mcbsp->dma_rx_lch, &eix, &fix) != 0) {

	fits in one line

> +		printk(KERN_ERR "OMAP_McBSP: Getting chain index failed\n");
> +		goto rxinx_err;
> +	}
> +
> +	*ei = eix;
> +	*fi = fix;
> +	return 0;
> +
> +rxinx_err:
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_receiver_index);
> +
> +/*
> + * Basic Reset Transmitter
> + * id		: McBSP interface number
> + * state	: Disable (0)/ Enable (1) the transmitter
> + */

kdoc style

> +int omap2_mcbsp_set_xrst(unsigned int id, u8 state)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	u32 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_XRST_DISABLE)
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +		      OMAP_MCBSP_READ(io_base, SPCR2) & (~XRST));
> +	else
> +		OMAP_MCBSP_WRITE(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) | XRST);
> +	udelay(10);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_set_xrst);
> +
> +/*
> + * Reset Receiver
> + * id		: McBSP interface number
> + * state	: Disable (0)/ Enable (1) the receiver
> + */

kdoc style

> +int omap2_mcbsp_set_rrst(unsigned int id, u8 state)
> +{
> +	struct omap_mcbsp *mcbsp = mcbsp_ptr[id];
> +	u32 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(io_base, SPCR1,
> +			OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST));
> +	else
> +		OMAP_MCBSP_WRITE(io_base, SPCR1,
> +		      OMAP_MCBSP_READ(io_base, SPCR1) | RRST);
> +	udelay(10);

add a blank line before return

> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_set_rrst);
> +
> +/*
> + * Configure the receiver parameters
> + * id		: McBSP Interface ID
> + * rp		: DMA Receive parameters
> + */

kdoc

> +int omap2_mcbsp_dma_recv_params(unsigned int id,
> +			struct omap_mcbsp_dma_transfer_params *rp)
> +{
> +	struct omap_mcbsp *mcbsp;
> +	u32 io_base;
> +	int err, chain_id = -1;
> +	struct omap_dma_channel_params rx_params;
> +	u32  dt = 0;

use reversed christmas tree here:

+	struct omap_dma_channel_params rx_params;
+	struct omap_mcbsp *mcbsp;
+	int err, chain_id = -1;
+	u32 io_base;
+	u32  dt = 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;
> +	dt = rp->word_length1;
> +
> +	if (dt == OMAP_MCBSP_WORD_8)
> +		rx_params.data_type = OMAP_DMA_DATA_TYPE_S8;
> +	else if (dt == OMAP_MCBSP_WORD_16)
> +		rx_params.data_type = OMAP_DMA_DATA_TYPE_S16;
> +	else if (dt == OMAP_MCBSP_WORD_32)
> +		rx_params.data_type = OMAP_DMA_DATA_TYPE_S32;
> +	else
> +		return -EINVAL;
> +
> +	rx_params.read_prio = DMA_CH_PRIO_HIGH;
> +	rx_params.write_prio = DMA_CH_PRIO_HIGH;
> +	rx_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
> +	rx_params.src_fi = 0;
> +	rx_params.trigger = mcbsp->dma_rx_sync;
> +	rx_params.src_or_dst_synch = 0x01;
> +	rx_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
> +	rx_params.src_ei = 0x0;
> +	/* Indexing is always in bytes - so multiply with dt */
> +
> +	dt = (rx_params.data_type == OMAP_DMA_DATA_TYPE_S8) ? 1 :
> +		(rx_params.data_type == OMAP_DMA_DATA_TYPE_S16) ? 2 : 4;
> +
> +	/* SKIP_FIRST and SKIP_SECOND- skip alternate data in 24 bit mono */
> +	if (rp->skip_alt == OMAP_MCBSP_SKIP_SECOND) {
> +		rx_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
> +		rx_params.dst_ei = (1);
> +		rx_params.dst_fi = (1) + ((-1) * dt);
> +	} else if (rp->skip_alt == OMAP_MCBSP_SKIP_FIRST) {
> +		rx_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
> +		rx_params.dst_ei = 1 + (-2) * dt;
> +		rx_params.dst_fi = 1 + (2) * dt;
> +	} else {
> +		rx_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
> +		rx_params.dst_ei = 0;
> +		rx_params.dst_fi = 0;
> +	}
> +
> +	mcbsp->rxskip_alt = rp->skip_alt;
> +	mcbsp->auto_reset &= ~OMAP_MCBSP_AUTO_RRST;
> +	mcbsp->auto_reset |=	(rp->auto_reset & OMAP_MCBSP_AUTO_RRST);

			why this tab ??

> +
> +	mcbsp->rx_word_length = rx_params.data_type << 0x1;
> +	if (rx_params.data_type == 0)
> +		mcbsp->rx_word_length = 1;
> +
> +	mcbsp->rx_callback = rp->callback;
> +	/* request for a chain of dma channels for data reception */
> +	if (mcbsp->dma_rx_lch == -1) {
> +		err = omap_request_dma_chain(id, "McBSP RX",
> +					 omap2_mcbsp_rx_dma_callback, &chain_id,
> +					 2, OMAP_DMA_DYNAMIC_CHAIN, rx_params);
					no spaces for identation

> +		if (err < 0) {
> +			printk(KERN_ERR "Receive path configuration failed \n");
> +			return -EINVAL;
> +		}
> +		mcbsp->dma_rx_lch = chain_id;
> +		mcbsp->rx_dma_chain_state = 0;
> +	} else {
> +		/* DMA params already set, modify the same!! */
> +		err = omap_modify_dma_chain_params(mcbsp->dma_rx_lch,
> +								 rx_params);
						no spaces for identation
> +		if (err < 0)
> +			return -EINVAL;

		where's the omap_free_dma_chain() ??

> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_dma_recv_params);
> +
> +/*
> + * Configure the transmitter parameters
> + * id		: McBSP Interface ID
> + * tp		: DMA Transfer parameters
> + */

follow kdoc

> +

no need for extra line here

> +int omap2_mcbsp_dma_trans_params(unsigned int id,
> +			struct omap_mcbsp_dma_transfer_params *tp)
> +{
> +	struct omap_mcbsp *mcbsp;
> +
> +	struct omap_dma_channel_params tx_params;
> +	int err = 0, chain_id = -1;
> +	u32 io_base;
> +	u32 dt = 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;
> +
> +	dt = tp->word_length1;
> +	if ((dt != OMAP_MCBSP_WORD_8) && (dt != OMAP_MCBSP_WORD_16)
> +						 && (dt != OMAP_MCBSP_WORD_32))
> +		return -EINVAL;
> +	if (dt == OMAP_MCBSP_WORD_8)
> +		tx_params.data_type = OMAP_DMA_DATA_TYPE_S8;
> +	else if (dt == OMAP_MCBSP_WORD_16)
> +		tx_params.data_type = OMAP_DMA_DATA_TYPE_S16;
> +	else if (dt == OMAP_MCBSP_WORD_32)
> +		tx_params.data_type = OMAP_DMA_DATA_TYPE_S32;
> +	else
> +		return -EINVAL;
> +
> +	tx_params.read_prio = DMA_CH_PRIO_HIGH;
> +	tx_params.write_prio = DMA_CH_PRIO_HIGH;
> +	tx_params.sync_mode = OMAP_DMA_SYNC_ELEMENT;
> +	tx_params.dst_fi = 0;
> +	tx_params.trigger = mcbsp->dma_tx_sync;
> +	tx_params.src_or_dst_synch = 0;
> +	tx_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
> +	tx_params.dst_ei = 0;
> +	/* Indexing is always in bytes - so multiply with dt */
> +	mcbsp->tx_word_length = tx_params.data_type << 0x1;
> +
> +	if (tx_params.data_type == 0)
> +		mcbsp->tx_word_length = 1;
> +	dt = mcbsp->tx_word_length;
> +
> +	/* SKIP_FIRST and SKIP_SECOND- skip alternate data in 24 bit mono */
> +	if (tp->skip_alt == OMAP_MCBSP_SKIP_SECOND) {
> +		tx_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
> +		tx_params.src_ei = (1);
> +		tx_params.src_fi = (1) + ((-1) * dt);
> +	} else if (tp->skip_alt == OMAP_MCBSP_SKIP_FIRST) {
> +		tx_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
> +		tx_params.src_ei = 1 + (-2) * dt;
> +		tx_params.src_fi = 1 + (2) * dt;
> +	} else {
> +		tx_params.src_amode = OMAP_DMA_AMODE_POST_INC;
> +		tx_params.src_ei = 0;
> +		tx_params.src_fi = 0;
> +	}
> +
> +	mcbsp->txskip_alt = tp->skip_alt;
> +	mcbsp->auto_reset &= ~OMAP_MCBSP_AUTO_XRST;
> +	mcbsp->auto_reset |=
> +		(tp->auto_reset & OMAP_MCBSP_AUTO_XRST);
> +	mcbsp->tx_callback = tp->callback;
> +
> +	/* Based on Rjust we can do double indexing DMA params configuration */
> +	if (mcbsp->dma_tx_lch == -1) {
> +		err = omap_request_dma_chain(id, "McBSP TX",
> +					 omap2_mcbsp_tx_dma_callback, &chain_id,
> +					 2, OMAP_DMA_DYNAMIC_CHAIN, tx_params);
> +		if (err < 0) {
> +			printk(KERN_ERR
> +				"Transmit path configuration failed \n");
> +			return -EINVAL;
> +		}
> +		mcbsp->tx_dma_chain_state = 0;
> +	mcbsp->dma_tx_lch = chain_id;

	fix this identation

> +	} else {
> +		/* DMA params already set, modify the same!! */
> +		err = omap_modify_dma_chain_params(mcbsp->dma_tx_lch,
> +								 tx_params);
> +		if (err < 0)
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_dma_trans_params);
> +
> +/*
> + * Start receving data on a McBSP interface
> + * id			: McBSP interface ID
> + * cbdata		: User data to be returned with callback
> + * buf_start_addr	: The destination address [physical address]
> + * buf_size		: Buffer size
> + */

kdoc

> +

trailing extra line

> +int omap2_mcbsp_receive_data(unsigned int id, void *cbdata,
> +			     dma_addr_t buf_start_addr, u32 buf_size)
> +{
> +	struct omap_mcbsp *mcbsp;
> +	u32 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->phy_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 (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_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;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_receive_data);
> +
> +/*
> + * 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
> + */

kdoc

> +int omap2_mcbsp_send_data(unsigned int id, void *cbdata,
> +			  dma_addr_t buf_start_addr, u32 buf_size)
> +{
> +	struct omap_mcbsp *mcbsp;
> +	u32 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;
> +	}

add an extra line here

> +	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(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, 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->phy_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(io_base, SPCR2,
> +			OMAP_MCBSP_READ(io_base, SPCR2) | XRST);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(omap2_mcbsp_send_data);
> 
>  #ifdef CONFIG_ARCH_OMAP24XX
>  static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
> @@ -176,6 +867,7 @@
>  static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
>  	{
>  		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
> +		.phy_base	= OMAP34XX_MCBSP1_BASE,
>  		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
>  		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
>  		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
> @@ -185,6 +877,7 @@
>  	},
>  	{
>  		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
> +		.phy_base	= OMAP34XX_MCBSP2_BASE,
>  		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
>  		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
>  		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
> @@ -194,6 +887,7 @@
>  	},
>  	{
>  		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP3_BASE),
> +		.phy_base	= OMAP34XX_MCBSP3_BASE,
>  		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
>  		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
>  		.ops		= &omap2_mcbsp_ops,
> @@ -201,6 +895,7 @@
>  	},
>  	{
>  		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP4_BASE),
> +		.phy_base	= OMAP34XX_MCBSP4_BASE,
>  		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
>  		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
>  		.ops		= &omap2_mcbsp_ops,
> @@ -208,6 +903,7 @@
>  	},
>  	{
>  		.virt_base	= OMAP2_IO_ADDRESS(OMAP34XX_MCBSP5_BASE),
> +		.phy_base	= OMAP34XX_MCBSP5_BASE,
>  		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
>  		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
>  		.ops		= &omap2_mcbsp_ops,
> Index: linux-omap-2.6/arch/arm/plat-omap/mcbsp.c
> ===================================================================
> --- linux-omap-2.6.orig/arch/arm/plat-omap/mcbsp.c	2008-08-26
> 19:13:47.000000000 +0530
> +++ linux-omap-2.6/arch/arm/plat-omap/mcbsp.c	2008-08-26 19:55:24.000000000 +0530
> @@ -23,6 +23,7 @@
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/io.h>
> +#include <linux/irq.h>
> 
>  #include <asm/arch/dma.h>
>  #include <asm/arch/mcbsp.h>
> @@ -46,14 +47,6 @@
>  		return __raw_readl(io_base + reg);
>  }
> 
> -#define OMAP_MCBSP_READ(base, reg) \
> -			omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
> -#define OMAP_MCBSP_WRITE(base, reg, val) \
> -			omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val)
> -
> -#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
> -#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
> -
>  static void omap_mcbsp_dump_reg(u8 id)
>  {
>  	struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
> @@ -173,6 +166,11 @@
>  	OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
>  	OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
>  	OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
> +	if (cpu_is_omap2430() || cpu_is_omap34xx()) {
> +		if (mcbsp->pdata->ops->config)
> +			mcbsp->pdata->ops->config(id, config);
> +	}
> +
>  }
>  EXPORT_SYMBOL(omap_mcbsp_config);
> 
> @@ -218,11 +216,11 @@
>  	}
>  	mcbsp = id_to_mcbsp_ptr(id);
> 
> +	clk_enable(mcbsp->clk);
> +
>  	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
>  		mcbsp->pdata->ops->request(id);
> 
> -	clk_enable(mcbsp->clk);
> -
>  	spin_lock(&mcbsp->lock);
>  	if (!mcbsp->free) {
>  		dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
> @@ -893,6 +891,7 @@
>  	mcbsp->dma_rx_lch = -1;
> 
>  	mcbsp->io_base = pdata->virt_base;
> +	mcbsp->phy_base = pdata->phy_base;
>  	/* Default I/O is IRQ based */
>  	mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
>  	mcbsp->tx_irq = pdata->tx_irq;
> Index: linux-omap-2.6/include/asm-arm/arch-omap/mcbsp.h
> ===================================================================
> --- linux-omap-2.6.orig/include/asm-arm/arch-omap/mcbsp.h	2008-08-26
> 19:13:47.000000000 +0530
> +++ linux-omap-2.6/include/asm-arm/arch-omap/mcbsp.h	2008-08-26
> 19:55:42.000000000 +0530
> @@ -239,31 +239,58 @@
>  /********************** McBSP SYSCONFIG bit definitions ********************/
>  #define SOFTRST			0x0002
> 
> +/********************** MACRO DEFINITIONS *********************************/
> +
> +/* McBSP interface operating mode */
> +#define OMAP_MCBSP_MASTER			1
> +#define OMAP_MCBSP_SLAVE			0
> +
> +#define OMAP_MCBSP_AUTO_RST_NONE		(0x0)
> +#define OMAP_MCBSP_AUTO_RRST			(0x1<<1)
> +#define OMAP_MCBSP_AUTO_XRST			(0x1<<2)
> +
> +/* SRG ENABLE/DISABLE state */
> +#define OMAP_MCBSP_ENABLE_FSG_SRG		1
> +#define OMAP_MCBSP_DISABLE_FSG_SRG		0
> +/* mono to mono mode*/
> +#define OMAP_MCBSP_SKIP_NONE			(0x0)
> +/* mono to stereo mode */
> +#define OMAP_MCBSP_SKIP_FIRST			(0x1<<1)
> +#define OMAP_MCBSP_SKIP_SECOND			(0x1<<2)
> +/* RRST STATE */
> +#define OMAP_MCBSP_RRST_DISABLE			0
> +#define OMAP_MCBSP_RRST_ENABLE			1
> +/*XRST STATE */
> +#define OMAP_MCBSP_XRST_DISABLE			0
> +#define OMAP_MCBSP_XRST_ENABLE			1
> +
>  /* we don't do multichannel for now */
>  struct omap_mcbsp_reg_cfg {
> -	u16 spcr2;
> -	u16 spcr1;
> -	u16 rcr2;
> -	u16 rcr1;
> -	u16 xcr2;
> -	u16 xcr1;
> -	u16 srgr2;
> -	u16 srgr1;
> -	u16 mcr2;
> -	u16 mcr1;
> -	u16 pcr0;
> -	u16 rcerc;
> -	u16 rcerd;
> -	u16 xcerc;
> -	u16 xcerd;
> -	u16 rcere;
> -	u16 rcerf;
> -	u16 xcere;
> -	u16 xcerf;
> -	u16 rcerg;
> -	u16 rcerh;
> -	u16 xcerg;
> -	u16 xcerh;
> +	u32 spcr2;
> +	u32 spcr1;
> +	u32 rcr2;
> +	u32 rcr1;
> +	u32 xcr2;
> +	u32 xcr1;
> +	u32 srgr2;
> +	u32 srgr1;
> +	u32 mcr2;
> +	u32 mcr1;
> +	u32 pcr0;
> +	u32 rcerc;
> +	u32 rcerd;
> +	u32 xcerc;
> +	u32 xcerd;
> +	u32 rcere;
> +	u32 rcerf;
> +	u32 xcere;
> +	u32 xcerf;
> +	u32 rcerg;
> +	u32 rcerh;
> +	u32 xcerg;
> +	u32 xcerh;
> +	u32 xccr;
> +	u32 rccr;
>  };
> 
>  typedef enum {
> @@ -277,6 +304,7 @@
>  typedef int __bitwise omap_mcbsp_io_type_t;
>  #define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
>  #define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
> +typedef void (*omap_mcbsp_dma_cb) (u32 ch_status, void *arg);
> 
>  typedef enum {
>  	OMAP_MCBSP_WORD_8 = 0,
> @@ -319,14 +347,28 @@
>  	omap_mcbsp_word_length		word_length;
>  };
> 
> +struct omap_mcbsp_dma_transfer_params {
> +	/* Skip the alternate element use fro stereo mode */
> +	u8 skip_alt;
> +	/* Automagically handle Transfer [XR]RST? */
> +	u8   auto_reset;
> +	/* callback function executed for every tx/rx completion */
> +	omap_mcbsp_dma_cb callback;
> +	/* word length of data */
> +	u32 word_length1;

this is difficult to read, add extra line after each variable:

+	/* Skip the alternate element use fro stereo mode */
+	u8 skip_alt;
+
+	/* Automagically handle Transfer [XR]RST? */
+	u8   auto_reset;
+
+	/* callback function executed for every tx/rx completion */
+	omap_mcbsp_dma_cb callback;
+
+	/* word length of data */
+	u32 word_length1;


> +

this is unnecessary

> +};
> +
>  /* Platform specific configuration */
>  struct omap_mcbsp_ops {
>  	void (*request)(unsigned int);
>  	void (*free)(unsigned int);
> +	void (*config)(unsigned int,  const struct omap_mcbsp_reg_cfg *config);
				 isn't one space enough ?
>  };
> 
>  struct omap_mcbsp_platform_data {
>  	u32 virt_base;
> +	u32 phy_base;
>  	u8 dma_rx_sync, dma_tx_sync;
>  	u16 rx_irq, tx_irq;
>  	struct omap_mcbsp_ops *ops;
> @@ -362,10 +404,32 @@
>  	spinlock_t lock;
>  	struct omap_mcbsp_platform_data *pdata;
>  	struct clk *clk;
> +	u32 phy_base;
> +	u8  auto_reset;	/* Auto Reset */
> +	u8  txskip_alt;	/* Tx skip flags */
> +	u8  rxskip_alt;	/* Rx skip flags */
> +	void  *rx_cb_arg;
> +	void  *tx_cb_arg;
> +	omap_mcbsp_dma_cb  rx_callback;
> +	omap_mcbsp_dma_cb  tx_callback;
> +	int  rx_dma_chain_state;
> +	int  tx_dma_chain_state;
> +	int  interface_mode; /* Master / Slave */

	one space only for all above. And make it reverse christmas tree

>  };
>  extern struct omap_mcbsp **mcbsp_ptr;
>  extern int omap_mcbsp_count;
> 
> +#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
> +#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
				how about aligning with the above one ?

> @@ -382,7 +446,6 @@
>  int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
>  int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
> 
> -

unnecessary change

> +int omap2_mcbsp_stop_datatx(unsigned int id);
> +int omap2_mcbsp_stop_datarx(u32 id);
> +int omap2_mcbsp_reset(unsigned int id);
> +int omap2_mcbsp_transmitter_index(int id, int *ei, int *fi);
> +int omap2_mcbsp_receiver_index(int id, int *ei, int *fi);
> +int omap2_mcbsp_set_xrst(unsigned int id, u8 state);
> +int omap2_mcbsp_set_rrst(unsigned int id, u8 state);
> +int omap2_mcbsp_dma_recv_params(unsigned int id,
> +			struct	omap_mcbsp_dma_transfer_params *rp);
				space, not tab. ditto below

-- 
balbi

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-08-28  8:26 [PATCH 1/2] McBSP DMA support for 34xx chandra shekhar
  2008-08-28 10:10 ` Felipe Balbi
@ 2008-08-28 10:52 ` Jarkko Nikula
  2008-08-28 11:20   ` shekhar, chandra
  1 sibling, 1 reply; 9+ messages in thread
From: Jarkko Nikula @ 2008-08-28 10:52 UTC (permalink / raw)
  To: ext chandra shekhar; +Cc: linux-omap

On Thu, 28 Aug 2008 13:56:00 +0530 (IST)
"ext chandra shekhar" <x0044955@ti.com> wrote:

> This patch supports DMA chaining mode and one time configuration for
> entire transfer to improve performance.
> Signed-off-by: chandra shekhar <x0044955@ti.com>
> ---
>  arch/arm/mach-omap2/mcbsp.c       |  702 ++++++++++++++++++++++++++++
> +++++++++- arch/arm/plat-omap/mcbsp.c        |   19 -
>  include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
>  3 files changed, 811 insertions(+), 37 deletions(-)
> 
Hi

What's the expected use case for DMA chaining mode or existing driver
which would get improved performance? There should have some reason why
this amount of new lines should be added.

Also ideally this should cover also OMAP1's from 16xx onward since they
can link DMA channels together as well?


Jarkko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-08-28 10:52 ` Jarkko Nikula
@ 2008-08-28 11:20   ` shekhar, chandra
  2008-09-09 16:31     ` Tony Lindgren
  0 siblings, 1 reply; 9+ messages in thread
From: shekhar, chandra @ 2008-08-28 11:20 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: linux-omap


----- Original Message ----- 
From: "Jarkko Nikula" <jarkko.nikula@nokia.com>
To: "ext chandra shekhar" <x0044955@ti.com>
Cc: <linux-omap@vger.kernel.org>
Sent: Thursday, August 28, 2008 4:22 PM
Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx


> On Thu, 28 Aug 2008 13:56:00 +0530 (IST)
> "ext chandra shekhar" <x0044955@ti.com> wrote:
>
>> This patch supports DMA chaining mode and one time configuration for
>> entire transfer to improve performance.
>> Signed-off-by: chandra shekhar <x0044955@ti.com>
>> ---
>>  arch/arm/mach-omap2/mcbsp.c       |  702 ++++++++++++++++++++++++++++
>> +++++++++- arch/arm/plat-omap/mcbsp.c        |   19 -
>>  include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
>>  3 files changed, 811 insertions(+), 37 deletions(-)
>>
> Hi
>
> What's the expected use case for DMA chaining mode or existing driver
> which would get improved performance? There should have some reason why
> this amount of new lines should be added.

current McBSP ( arch/arm/plat-omap/mcbsp.c) code request and releases dma 
channel for each transfer .
so there is latency involved. Chaining help with smooth audio play because we 
can enque the buffer
while another transfer is ongoing.

>
> Also ideally this should cover also OMAP1's from 16xx onward since they
> can link DMA channels together as well?

Current code might even work for 16xx and later versions for 16 bit data. ( or 
can be extended to work on 16xx and later versions)
but i dont have board or TRM to check for any changes in DMA subsytem or McBSP. 
better to play safe.

2430 onwards McBSP dxr/drr is 32 bits, which allows 24 bit mono/stereo transfer 
easily. if we had to have 16 bit dxr1,2/drr1,2
then we will have to perform the manipulation on data for 24 bit ops. we will 
have to consider all the options before extending it to 16xx.

>
>
> Jarkko
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-08-28 11:20   ` shekhar, chandra
@ 2008-09-09 16:31     ` Tony Lindgren
  2008-09-10 10:17       ` shekhar, chandra
  0 siblings, 1 reply; 9+ messages in thread
From: Tony Lindgren @ 2008-09-09 16:31 UTC (permalink / raw)
  To: shekhar, chandra; +Cc: Jarkko Nikula, linux-omap

* shekhar, chandra <x0044955@ti.com> [080828 04:21]:
>
> ----- Original Message ----- From: "Jarkko Nikula" 
> <jarkko.nikula@nokia.com>
> To: "ext chandra shekhar" <x0044955@ti.com>
> Cc: <linux-omap@vger.kernel.org>
> Sent: Thursday, August 28, 2008 4:22 PM
> Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx
>
>
>> On Thu, 28 Aug 2008 13:56:00 +0530 (IST)
>> "ext chandra shekhar" <x0044955@ti.com> wrote:
>>
>>> This patch supports DMA chaining mode and one time configuration for
>>> entire transfer to improve performance.
>>> Signed-off-by: chandra shekhar <x0044955@ti.com>
>>> ---
>>>  arch/arm/mach-omap2/mcbsp.c       |  702 ++++++++++++++++++++++++++++
>>> +++++++++- arch/arm/plat-omap/mcbsp.c        |   19 -
>>>  include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
>>>  3 files changed, 811 insertions(+), 37 deletions(-)
>>>
>> Hi
>>
>> What's the expected use case for DMA chaining mode or existing driver
>> which would get improved performance? There should have some reason why
>> this amount of new lines should be added.
>
> current McBSP ( arch/arm/plat-omap/mcbsp.c) code request and releases dma 
> channel for each transfer .
> so there is latency involved. Chaining help with smooth audio play 
> because we can enque the buffer
> while another transfer is ongoing.

But the omap ASoC does already circular dma that automatically loops back
to the beginning of fifo as long as there's data. How would the chaining help
with this?

Maybe update your codec to work with omap ASoC and see if you still
need chaining?

Tony


>
>>
>> Also ideally this should cover also OMAP1's from 16xx onward since they
>> can link DMA channels together as well?
>
> Current code might even work for 16xx and later versions for 16 bit data. 
> ( or can be extended to work on 16xx and later versions)
> but i dont have board or TRM to check for any changes in DMA subsytem or 
> McBSP. better to play safe.
>
> 2430 onwards McBSP dxr/drr is 32 bits, which allows 24 bit mono/stereo 
> transfer easily. if we had to have 16 bit dxr1,2/drr1,2
> then we will have to perform the manipulation on data for 24 bit ops. we 
> will have to consider all the options before extending it to 16xx.
>
>>
>>
>> Jarkko
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-09-09 16:31     ` Tony Lindgren
@ 2008-09-10 10:17       ` shekhar, chandra
  2008-09-10 11:14         ` Jarkko Nikula
  0 siblings, 1 reply; 9+ messages in thread
From: shekhar, chandra @ 2008-09-10 10:17 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Jarkko Nikula, linux-omap


----- Original Message ----- 
From: "Tony Lindgren" <tony@atomide.com>
To: "shekhar, chandra" <x0044955@ti.com>
Cc: "Jarkko Nikula" <jarkko.nikula@nokia.com>; <linux-omap@vger.kernel.org>
Sent: Tuesday, September 09, 2008 10:01 PM
Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx


>* shekhar, chandra <x0044955@ti.com> [080828 04:21]:
>>
>> ----- Original Message ----- From: "Jarkko Nikula"
>> <jarkko.nikula@nokia.com>
>> To: "ext chandra shekhar" <x0044955@ti.com>
>> Cc: <linux-omap@vger.kernel.org>
>> Sent: Thursday, August 28, 2008 4:22 PM
>> Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx
>>
>>
>>> On Thu, 28 Aug 2008 13:56:00 +0530 (IST)
>>> "ext chandra shekhar" <x0044955@ti.com> wrote:
>>>
>>>> This patch supports DMA chaining mode and one time configuration for
>>>> entire transfer to improve performance.
>>>> Signed-off-by: chandra shekhar <x0044955@ti.com>
>>>> ---
>>>>  arch/arm/mach-omap2/mcbsp.c       |  702 ++++++++++++++++++++++++++++
>>>> +++++++++- arch/arm/plat-omap/mcbsp.c        |   19 -
>>>>  include/asm-arm/arch-omap/mcbsp.h |  127 +++++-
>>>>  3 files changed, 811 insertions(+), 37 deletions(-)
>>>>
>>> Hi
>>>
>>> What's the expected use case for DMA chaining mode or existing driver
>>> which would get improved performance? There should have some reason why
>>> this amount of new lines should be added.
>>
>> current McBSP ( arch/arm/plat-omap/mcbsp.c) code request and releases dma
>> channel for each transfer .
>> so there is latency involved. Chaining help with smooth audio play
>> because we can enque the buffer
>> while another transfer is ongoing.
>
> But the omap ASoC does already circular dma that automatically loops back
> to the beginning of fifo as long as there's data. How would the chaining help
> with this?
>
> Maybe update your codec to work with omap ASoC and see if you still
> need chaining?
>

Yes, Codec driver can be modified to adapt OMAP ASoC.
but there are some additional features.

1> 16/24 bit mono and stereo data transfer
2>  Separate Rx and Tx path, enable only respective path.
3>  data transfer in 8,16,32 bit mode

Most importantly,
4> McBSP buffer ( To save power, for 34xx).
OMAP3430 McBSP interface 2 has 5k buffer for audio.  handling of this buffer 
should be specific to McBSP.

Apart from that this is a generic McBSP code which will not interrupt the ASoC 
functionality.

In OMAP ASoC code the channel is linked to itself , i am not sure about latency 
in that case, but if DMA channels are available
we can use chaining of two channels in ASoC. this might reduce latency.




>
>>
>>>
>>> Also ideally this should cover also OMAP1's from 16xx onward since they
>>> can link DMA channels together as well?
>>
>> Current code might even work for 16xx and later versions for 16 bit data.
>> ( or can be extended to work on 16xx and later versions)
>> but i dont have board or TRM to check for any changes in DMA subsytem or
>> McBSP. better to play safe.
>>
>> 2430 onwards McBSP dxr/drr is 32 bits, which allows 24 bit mono/stereo
>> transfer easily. if we had to have 16 bit dxr1,2/drr1,2
>> then we will have to perform the manipulation on data for 24 bit ops. we
>> will have to consider all the options before extending it to 16xx.
>>
>>>
>>>
>>> Jarkko
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-09-10 10:17       ` shekhar, chandra
@ 2008-09-10 11:14         ` Jarkko Nikula
  2008-09-10 11:44           ` shekhar, chandra
  0 siblings, 1 reply; 9+ messages in thread
From: Jarkko Nikula @ 2008-09-10 11:14 UTC (permalink / raw)
  To: ext shekhar, chandra; +Cc: Tony Lindgren, linux-omap

On Wed, 10 Sep 2008 15:47:34 +0530
"ext shekhar, chandra" <x0044955@ti.com> wrote:

> Most importantly,
> 4> McBSP buffer ( To save power, for 34xx).
> OMAP3430 McBSP interface 2 has 5k buffer for audio.  handling of this
> buffer should be specific to McBSP.
> 
Actually it's not specific to McBSP only. I haven't paid attention into
these HW buffering issues but they have an effect. Like

- IRCC ALSA expects that playback/record is really stopped when trigger
  callback returns
- How HW buffering affects pointer callback? Some low-latency audio
  algorithms require that buffer position is known very precisely. E.g.
  if modifying already queued audio buffer content but which is not
  played out yet


Jarkko

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-09-10 11:14         ` Jarkko Nikula
@ 2008-09-10 11:44           ` shekhar, chandra
  2008-09-24  9:28             ` Tony Lindgren
  0 siblings, 1 reply; 9+ messages in thread
From: shekhar, chandra @ 2008-09-10 11:44 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: Tony Lindgren, linux-omap


----- Original Message ----- 
From: "Jarkko Nikula" <jarkko.nikula@nokia.com>
To: "ext shekhar, chandra" <x0044955@ti.com>
Cc: "Tony Lindgren" <tony@atomide.com>; <linux-omap@vger.kernel.org>
Sent: Wednesday, September 10, 2008 4:44 PM
Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx


> On Wed, 10 Sep 2008 15:47:34 +0530
> "ext shekhar, chandra" <x0044955@ti.com> wrote:
>
>> Most importantly,
>> 4> McBSP buffer ( To save power, for 34xx).
>> OMAP3430 McBSP interface 2 has 5k buffer for audio.  handling of this
>> buffer should be specific to McBSP.
>>
> Actually it's not specific to McBSP only. I haven't paid attention into
> these HW buffering issues but they have an effect. Like
>
> - IRCC ALSA expects that playback/record is really stopped when trigger
>  callback returns
> - How HW buffering affects pointer callback? Some low-latency audio
>  algorithms require that buffer position is known very precisely. E.g.
>  if modifying already queued audio buffer content but which is not
>  played out yet

This harware buffer is not user accessible, but during data transfer it is 
related to dma transfer.
During data transfer instead of element sync, packet sync data transfer can be 
used.
DMA request length can be configured buffer threshold and packet sync transfer 
can be used instead of element sync.

>
> Jarkko
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2]  McBSP DMA support for  34xx
  2008-09-10 11:44           ` shekhar, chandra
@ 2008-09-24  9:28             ` Tony Lindgren
  0 siblings, 0 replies; 9+ messages in thread
From: Tony Lindgren @ 2008-09-24  9:28 UTC (permalink / raw)
  To: shekhar, chandra; +Cc: Jarkko Nikula, linux-omap

* shekhar, chandra <x0044955@ti.com> [080910 14:45]:
>
> ----- Original Message ----- From: "Jarkko Nikula" 
> <jarkko.nikula@nokia.com>
> To: "ext shekhar, chandra" <x0044955@ti.com>
> Cc: "Tony Lindgren" <tony@atomide.com>; <linux-omap@vger.kernel.org>
> Sent: Wednesday, September 10, 2008 4:44 PM
> Subject: Re: [PATCH 1/2] McBSP DMA support for 34xx
>
>
>> On Wed, 10 Sep 2008 15:47:34 +0530
>> "ext shekhar, chandra" <x0044955@ti.com> wrote:
>>
>>> Most importantly,
>>> 4> McBSP buffer ( To save power, for 34xx).
>>> OMAP3430 McBSP interface 2 has 5k buffer for audio.  handling of this
>>> buffer should be specific to McBSP.
>>>
>> Actually it's not specific to McBSP only. I haven't paid attention into
>> these HW buffering issues but they have an effect. Like
>>
>> - IRCC ALSA expects that playback/record is really stopped when trigger
>>  callback returns
>> - How HW buffering affects pointer callback? Some low-latency audio
>>  algorithms require that buffer position is known very precisely. E.g.
>>  if modifying already queued audio buffer content but which is not
>>  played out yet
>
> This harware buffer is not user accessible, but during data transfer it 
> is related to dma transfer.
> During data transfer instead of element sync, packet sync data transfer 
> can be used.
> DMA request length can be configured buffer threshold and packet sync 
> transfer can be used instead of element sync.

Let's put these on hold until we see the use cases. We should first
get all the other pending mcbsp patches into the mainline kernel, and
then all legacy audio code removed from l-o tree.

Then let's see how we can make use of the McBSP fifo and chaining if
needed.

Cheers,

Tony

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-09-24  9:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-28  8:26 [PATCH 1/2] McBSP DMA support for 34xx chandra shekhar
2008-08-28 10:10 ` Felipe Balbi
2008-08-28 10:52 ` Jarkko Nikula
2008-08-28 11:20   ` shekhar, chandra
2008-09-09 16:31     ` Tony Lindgren
2008-09-10 10:17       ` shekhar, chandra
2008-09-10 11:14         ` Jarkko Nikula
2008-09-10 11:44           ` shekhar, chandra
2008-09-24  9:28             ` Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox