summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShubhro <a0393217@ti.com>2010-02-11 14:42:29 +0530
committerRicardo Perez Olivares <x0081762@ti.com>2010-02-11 03:39:56 -0600
commit0aa31d7a79909779d96a5ee2e80b8efd22d46221 (patch)
tree9716aced65c9006252930ade4f24c3346625b966
parent1f430fc92eb18dd7326932a78127ba8e3ff34490 (diff)
Signed-off-by: Shubhro <a0393217@ti.com>
-rw-r--r--arch/arm/mach-omap2/mcbsp.c943
-rw-r--r--arch/arm/plat-omap/include/plat/clock.h2
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h183
-rw-r--r--arch/arm/plat-omap/mcbsp.c6
4 files changed, 1132 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index baa451733850..ead8e1f4788f 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/delay.h>
#include <linux/platform_device.h>
#include <mach/irqs.h>
@@ -22,6 +23,117 @@
#include <plat/mux.h>
#include <plat/cpu.h>
#include <plat/mcbsp.h>
+#include <plat/dma.h>
+
+#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)
+
+struct omap_mcbsp_reg_cfg mcbsp_cfg = {0};
+
+struct mcbsp_internal_clk {
+ struct clk clk;
+ struct clk **childs;
+ int n_childs;
+};
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
+static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
+{
+ const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
+ int i;
+
+ mclk->n_childs = ARRAY_SIZE(clk_names);
+ mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
+ GFP_KERNEL);
+
+ for (i = 0; i < mclk->n_childs; i++) {
+ /* We fake a platform device to get correct device id */
+ struct platform_device pdev;
+
+ pdev.dev.bus = &platform_bus_type;
+ pdev.id = mclk->clk.id;
+ mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
+ if (IS_ERR(mclk->childs[i]))
+ printk(KERN_ERR "Could not get clock %s (%d).\n",
+ clk_names[i], mclk->clk.id);
+ }
+}
+
+static int omap_mcbsp_clk_enable(struct clk *clk)
+{
+ struct mcbsp_internal_clk *mclk = container_of(clk,
+ struct mcbsp_internal_clk, clk);
+ int i;
+ for (i = 0; i < mclk->n_childs; i)
+ clk_enable(mclk->childs[i]);
+ return 0;
+}
+
+static void omap_mcbsp_clk_disable(struct clk *clk)
+{
+ struct mcbsp_internal_clk *mclk = container_of(clk,
+ struct mcbsp_internal_clk, clk);
+ int i;
+
+ for (i = 0; i < mclk->n_childs; i++)
+ clk_disable(mclk->childs[i]);
+}
+
+
+static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
+ {
+ .clk = {
+ .name = "mcbsp_clk",
+ .id = 1,
+ .enable = omap_mcbsp_clk_enable,
+ .disable = omap_mcbsp_clk_disable,
+ },
+ },
+ {
+ .clk = {
+ .name = "mcbsp_clk",
+ .id = 2,
+ .enable = omap_mcbsp_clk_enable,
+ .disable = omap_mcbsp_clk_disable,
+ },
+ },
+ {
+ .clk = {
+ .name = "mcbsp_clk",
+ .id = 3,
+ .enable = omap_mcbsp_clk_enable,
+ .disable = omap_mcbsp_clk_disable,
+ },
+ },
+ {
+ .clk = {
+ .name = "mcbsp_clk",
+ .id = 4,
+ .enable = omap_mcbsp_clk_enable,
+ .disable = omap_mcbsp_clk_disable,
+ },
+ },
+ {
+ .clk = {
+ .name = "mcbsp_clk",
+ .id = 5,
+ .enable = omap_mcbsp_clk_enable,
+ .disable = omap_mcbsp_clk_disable,
+ },
+ },
+};
+
+
+#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
+
+#else
+#define omap_mcbsp_clks_size 0
+static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
+static inline void omap_mcbsp_clk_init(struct clk *clk)
+{ }
+#endif
static void omap2_mcbsp2_mux_setup(void)
{
@@ -209,8 +321,839 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
};
#define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata)
+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;
+ void __iomem *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 void omap2_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+ struct omap_mcbsp *mcbsp_dma_rx = data;
+ void __iomem *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;
+ 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(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];
+ void __iomem *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];
+ 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_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];
+ 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(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);
+
+/*
+ * 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];
+ 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_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];
+ 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(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;
+ void __iomem *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;
+ void __iomem *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;
+ 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 (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;
+ 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(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->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(io_base, SPCR2,
+ OMAP_MCBSP_READ(io_base, SPCR2) | XRST);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_send_data);
+
+void omap2_mcbsp_set_recv_param(struct omap_mcbsp_reg_cfg *mcbsp_cfg,
+ struct omap_mcbsp_cfg_param *rp)
+{
+ mcbsp_cfg->spcr1 = RJUST(rp->justification);
+ mcbsp_cfg->rcr2 = RCOMPAND(rp->reverse_compand) |
+ RDATDLY(rp->data_delay);
+ if (rp->phase == OMAP_MCBSP_FRAME_SINGLEPHASE)
+ mcbsp_cfg->rcr2 = mcbsp_cfg->rcr2 & ~(RPHASE);
+ else
+ mcbsp_cfg->rcr2 = mcbsp_cfg->rcr2 | (RPHASE) |
+ RWDLEN2(rp->word_length2) | RFRLEN2(rp->frame_length2);
+ mcbsp_cfg->rcr1 = RWDLEN1(rp->word_length1) |
+ RFRLEN1(rp->frame_length1);
+ if (rp->fsync_src == OMAP_MCBSP_RXFSYNC_INTERNAL)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | FSRM;
+ if (rp->clk_mode == OMAP_MCBSP_CLKRXSRC_INTERNAL)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | CLKRM;
+ if (rp->clk_polarity == OMAP_MCBSP_CLKR_POLARITY_RISING)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | CLKRP;
+ if (rp->fs_polarity == OMAP_MCBSP_FS_ACTIVE_LOW)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | FSRP;
+ return;
+}
+
+/*
+ * Set McBSP transmit parameters
+ * id : McBSP interface ID
+ * mcbsp_cfg : McBSP register configuration
+ * tp : McBSP transmit parameters
+ */
+
+void omap2_mcbsp_set_trans_param(struct omap_mcbsp_reg_cfg *mcbsp_cfg,
+ struct omap_mcbsp_cfg_param *tp)
+{
+ mcbsp_cfg->xcr2 = XCOMPAND(tp->reverse_compand) |
+ XDATDLY(tp->data_delay);
+ if (tp->phase == OMAP_MCBSP_FRAME_SINGLEPHASE)
+ mcbsp_cfg->xcr2 = mcbsp_cfg->xcr2 & ~(XPHASE);
+ else
+ mcbsp_cfg->xcr2 = mcbsp_cfg->xcr2 | (XPHASE) |
+ RWDLEN2(tp->word_length2) | RFRLEN2(tp->frame_length2);
+ mcbsp_cfg->xcr1 = XWDLEN1(tp->word_length1) |
+ XFRLEN1(tp->frame_length1);
+ if (tp->fs_polarity == OMAP_MCBSP_FS_ACTIVE_LOW)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | FSXP;
+ if (tp->fsync_src == OMAP_MCBSP_TXFSYNC_INTERNAL)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | FSXM;
+ if (tp->clk_mode == OMAP_MCBSP_CLKTXSRC_INTERNAL)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | CLKXM;
+ if (tp->clk_polarity == OMAP_MCBSP_CLKX_POLARITY_FALLING)
+ mcbsp_cfg->pcr0 = mcbsp_cfg->pcr0 | CLKXP;
+ return;
+}
+
+ /*
+ * Set McBSP SRG configuration
+ * id : McBSP interface ID
+ * mcbsp_cfg : McBSP register configuration
+ * interface_mode : Master/Slave
+ * param : McBSP SRG and FSG configuration
+ */
+
+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(omap_mcbsp_clks[id].childs[1]);
+ clkgdv = clk_rate / (param->sample_rate *
+ (param->bits_per_sample - 1));
+ 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(io_base, XCCR);
+ if (param->dlb)
+ mcbsp_cfg->xccr = mcbsp_cfg->xccr | (DILB);
+ mcbsp_cfg->rccr = OMAP_MCBSP_READ(io_base, RCCR);
+
+ return;
+ }
+
+/*
+ * configure the McBSP registers
+ * id : McBSP interface ID
+ * interface_mode : Master/Slave
+ * rp : McBSP recv parameters
+ * tp : McBSP transmit parameters
+ * param : McBSP SRG and FSG configuration
+ */
+void omap2_mcbsp_params_cfg(unsigned int id, int interface_mode,
+ struct omap_mcbsp_cfg_param *rp,
+ struct omap_mcbsp_cfg_param *tp,
+ struct omap_mcbsp_srg_fsg_cfg *param)
+{
+ if (rp)
+ omap2_mcbsp_set_recv_param(&mcbsp_cfg, rp);
+ if (tp)
+ omap2_mcbsp_set_trans_param(&mcbsp_cfg, tp);
+ if (param)
+ omap2_mcbsp_set_srg_cfg_param(id,
+ interface_mode, &mcbsp_cfg, param);
+ omap_mcbsp_config(id, &mcbsp_cfg);
+
+ return;
+}
+EXPORT_SYMBOL(omap2_mcbsp_params_cfg);
+
+
static int __init omap2_mcbsp_init(void)
{
+ int i;
+
+ for (i = 0; i < omap_mcbsp_clks_size; i++) {
+ /* Once we call clk_get inside init, we do not register it */
+ omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
+ clk_register(&omap_mcbsp_clks[i].clk);
+ }
+
if (cpu_is_omap2420())
omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
if (cpu_is_omap2430())
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 309b6d1dccdb..dc34717ed8bf 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -86,6 +86,8 @@ struct clk {
int (*set_rate)(struct clk *, unsigned long);
long (*round_rate)(struct clk *, unsigned long);
void (*init)(struct clk *);
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
__u8 enable_bit;
__s8 usecount;
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 4f22e5bb7ff7..393e8eb38adf 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -29,6 +29,7 @@
#include <mach/hardware.h>
#include <plat/clock.h>
+#include <plat/dma.h>
#define OMAP7XX_MCBSP1_BASE 0xfffb1000
#define OMAP7XX_MCBSP2_BASE 0xfffb1800
@@ -265,6 +266,95 @@
#define ENAWAKEUP 0x0004
#define SOFTRST 0x0002
+#define OMAP_MCBSP_WORDLEN_NONE 255
+
+#define OMAP_MCBSP_MASTER 1
+#define OMAP_MCBSP_SLAVE 0
+
+/* 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 2
+/* 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
+
+#define OMAP_MCBSP_FRAME_SINGLEPHASE 1
+#define OMAP_MCBSP_FRAME_DUALPHASE 2
+
+/* Sample Rate Generator Clock source */
+#define OMAP_MCBSP_SRGCLKSRC_CLKS 1
+#define OMAP_MCBSP_SRGCLKSRC_FCLK 2
+#define OMAP_MCBSP_SRGCLKSRC_CLKR 3
+#define OMAP_MCBSP_SRGCLKSRC_CLKX 4
+/* SRG input clock polarity */
+#define OMAP_MCBSP_CLKS_POLARITY_RISING 1
+#define OMAP_MCBSP_CLKS_POLARITY_FALLING 2
+
+#define OMAP_MCBSP_CLKX_POLARITY_RISING 1
+#define OMAP_MCBSP_CLKX_POLARITY_FALLING 2
+
+#define OMAP_MCBSP_CLKR_POLARITY_RISING 1
+#define OMAP_MCBSP_CLKR_POLARITY_FALLING 2
+
+/* SRG Clock synchronization mode */
+#define OMAP_MCBSP_SRG_FREERUNNING 1
+#define OMAP_MCBSP_SRG_RUNNING 2
+
+/* Frame Sync Source */
+#define OMAP_MCBSP_TXFSYNC_EXTERNAL 0
+#define OMAP_MCBSP_TXFSYNC_INTERNAL 1
+
+#define OMAP_MCBSP_RXFSYNC_EXTERNAL 0
+#define OMAP_MCBSP_RXFSYNC_INTERNAL 1
+
+#define OMAP_MCBSP_CLKRXSRC_EXTERNAL 1
+#define OMAP_MCBSP_CLKRXSRC_INTERNAL 2
+
+#define OMAP_MCBSP_CLKTXSRC_EXTERNAL 1
+#define OMAP_MCBSP_CLKTXSRC_INTERNAL 2
+
+/* Justification */
+#define OMAP_MCBSP_RJUST_ZEROMSB 0
+#define OMAP_MCBSP_RJUST_SIGNMSB 1
+#define OMAP_MCBSP_LJUST_ZEROLSB 2
+
+#define OMAP_MCBSP_DATADELAY0 0
+#define OMAP_MCBSP_DATADELAY1 1
+#define OMAP_MCBSP_DATADELAY2 2
+
+/* Reverse mode for 243X and 34XX */
+#define OMAP_MCBSP_MSBFIRST 0
+#define OMAP_MCBSP_LSBFIRST 1
+
+/* Multi-Channel partition mode */
+#define OMAP_MCBSP_TWOPARTITION_MODE 0
+#define OMAP_MCBSP_EIGHTPARTITION_MODE 1
+
+/* Rx Multichannel selection */
+#define OMAP_MCBSP_RXMUTICH_DISABLE 0
+#define OMAP_MCBSP_RXMUTICH_ENABLE 1
+
+/* Tx Multichannel selection */
+#define OMAP_MCBSP_TXMUTICH_DISABLE 0
+#define OMAP_MCBSP_TXMUTICH_ENABLE 1
+
+#define OMAP_MCBSP_FRAMELEN_N(NUM_WORDS) ((NUM_WORDS - 1) & 0x7F)
+
/********************** McBSP DMA operating modes **************************/
#define MCBSP_DMA_MODE_ELEMENT 0
#define MCBSP_DMA_MODE_THRESHOLD 1
@@ -321,6 +411,22 @@ typedef enum {
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)
+#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
+
+typedef void (*omap_mcbsp_dma_cb) (u32 ch_status, void *arg);
+
+typedef struct omap_mcbsp_dma_transfer_parameters {
+
+ /* 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;
+} omap_mcbsp_dma_transfer_params;
typedef enum {
OMAP_MCBSP_WORD_8 = 0,
@@ -410,12 +516,65 @@ struct omap_mcbsp {
struct omap_mcbsp_platform_data *pdata;
struct clk *iclk;
struct clk *fclk;
+
+ 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 */
+ struct omap_dma_channel_params rx_params; /* Used For Rx FIFO */
+ int rx_config_done;
+
#ifdef CONFIG_ARCH_OMAP34XX
int dma_op_mode;
u16 max_tx_thres;
u16 max_rx_thres;
#endif
};
+
+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;
+};
+
+struct omap_mcbsp_cfg_param {
+ u8 fsync_src;
+ u8 fs_polarity;
+ u8 clk_polarity;
+ u8 clk_mode;
+ u8 frame_length1;
+ u8 frame_length2;
+ u8 word_length1;
+ u8 word_length2;
+ u8 justification;
+ u8 reverse_compand;
+ u8 phase;
+ u8 data_delay;
+};
+
+struct omap_mcbsp_srg_fsg_cfg {
+ u32 period; /* Frame period */
+ u32 pulse_width; /* Frame width */
+ u8 fsgm;
+ u32 sample_rate;
+ u32 bits_per_sample;
+ u32 srg_src;
+ u8 sync_mode; /* SRG free running mode */
+ u8 polarity;
+ u8 dlb; /* digital loopback mode */
+};
+
extern struct omap_mcbsp **mcbsp_ptr;
extern int omap_mcbsp_count;
@@ -450,6 +609,30 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
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);
+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);
+extern int omap2_mcbsp_set_xrst(unsigned int id, u8 state);
+extern int omap2_mcbsp_set_rrst(unsigned int id, u8 state);
+extern int omap2_mcbsp_dma_recv_params(unsigned int id,
+ struct omap_mcbsp_dma_transfer_params *rp);
+extern int omap2_mcbsp_dma_trans_params(unsigned int id,
+ struct omap_mcbsp_dma_transfer_params *tp);
+extern int omap2_mcbsp_receive_data(unsigned int id, void *cbdata,
+ dma_addr_t buf_start_addr, u32 buf_size);
+extern int omap2_mcbsp_send_data(unsigned int id, void *cbdata,
+ dma_addr_t buf_start_addr, u32 buf_size);
+
+extern void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val);
+extern int omap_mcbsp_read(void __iomem *io_base, u16 reg);
+
+extern void omap2_mcbsp_params_cfg(unsigned int id, int interface_mode,
+ struct omap_mcbsp_cfg_param *rp,
+ struct omap_mcbsp_cfg_param *tp,
+ struct omap_mcbsp_srg_fsg_cfg *param);
+
/* SPI specific API */
void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 8eb8fb8654e6..7219b70079fe 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -37,6 +37,7 @@ void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val)
else
__raw_writel(val, io_base + reg);
}
+EXPORT_SYMBOL(omap_mcbsp_write);
int omap_mcbsp_read(void __iomem *io_base, u16 reg)
{
@@ -45,6 +46,7 @@ int omap_mcbsp_read(void __iomem *io_base, u16 reg)
else
return __raw_readl(io_base + reg);
}
+EXPORT_SYMBOL(omap_mcbsp_read);
#define OMAP_MCBSP_READ(base, reg) \
omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
@@ -527,11 +529,11 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
/* Enable transmitter and receiver */
tx &= 1;
w = OMAP_MCBSP_READ(io_base, SPCR2);
- OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
rx &= 1;
w = OMAP_MCBSP_READ(io_base, SPCR1);
- OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
/*
* Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec