* [PATCH 0/6] Convert JZ4740 to dmaengine
@ 2013-05-23 20:36 Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 1/6] MIPS: jz4740: Correct clock gate bit for DMA controller Lars-Peter Clausen
` (6 more replies)
0 siblings, 7 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
Hi,
This series replaces the custom JZ4740 DMA API with a dmaengine driver. This is
done in 3 steps:
1) Add a dmaengine driver which wraps the custom JZ4740 DMA API
2) Update all users of the JZ4740 DMA API to use dmaengine instead
3) Remove the custom API and move all direct hardware access to the
dmaengine driver.
The first two patches in the series also make sure that the clock of the DMA
core is enabled.
Since the patches in this series depend on each other I'd prefer if they could
all go through the DMA tree.
- Lars
Lars-Peter Clausen (4):
dma: Add a jz4740 dmaengine driver
MIPS: jz4740: Register jz4740 DMA device
ASoC: jz4740: Use the generic dmaengine PCM driver
MIPS: jz4740: Remove custom DMA API
Maarten ter Huurne (2):
MIPS: jz4740: Correct clock gate bit for DMA controller
MIPS: jz4740: Acquire and enable DMA controller clock
arch/mips/include/asm/mach-jz4740/dma.h | 56 ---
arch/mips/include/asm/mach-jz4740/platform.h | 1 +
arch/mips/jz4740/Makefile | 2 +-
arch/mips/jz4740/board-qi_lb60.c | 1 +
arch/mips/jz4740/clock.c | 2 +-
arch/mips/jz4740/dma.c | 287 -------------
arch/mips/jz4740/platform.c | 21 +
drivers/dma/Kconfig | 6 +
drivers/dma/Makefile | 1 +
drivers/dma/dma-jz4740.c | 616 +++++++++++++++++++++++++++
sound/soc/jz4740/Kconfig | 1 +
sound/soc/jz4740/jz4740-i2s.c | 48 +--
sound/soc/jz4740/jz4740-pcm.c | 310 +-------------
sound/soc/jz4740/jz4740-pcm.h | 20 -
14 files changed, 675 insertions(+), 697 deletions(-)
delete mode 100644 arch/mips/jz4740/dma.c
create mode 100644 drivers/dma/dma-jz4740.c
delete mode 100644 sound/soc/jz4740/jz4740-pcm.h
--
1.8.2.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/6] MIPS: jz4740: Correct clock gate bit for DMA controller
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 2/6] MIPS: jz4740: Acquire and enable DMA controller clock Lars-Peter Clausen
` (5 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
From: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
arch/mips/jz4740/clock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 484d38a..1b5f554 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -687,7 +687,7 @@ static struct clk jz4740_clock_simple_clks[] = {
[3] = {
.name = "dma",
.parent = &jz_clk_high_speed_peripheral.clk,
- .gate_bit = JZ_CLOCK_GATE_UART0,
+ .gate_bit = JZ_CLOCK_GATE_DMAC,
.ops = &jz_clk_simple_ops,
},
[4] = {
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/6] MIPS: jz4740: Acquire and enable DMA controller clock
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 1/6] MIPS: jz4740: Correct clock gate bit for DMA controller Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 3/6] dma: Add a jz4740 dmaengine driver Lars-Peter Clausen
` (4 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
From: Maarten ter Huurne <maarten@treewalker.org>
Previously, it was assumed that the DMA controller clock is not gated
when the kernel starts running. While that is the power-on state, it is
safer to not rely on that.
Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
arch/mips/jz4740/dma.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c
index 317ec6f..0e34b97 100644
--- a/arch/mips/jz4740/dma.c
+++ b/arch/mips/jz4740/dma.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
@@ -268,6 +269,7 @@ static irqreturn_t jz4740_dma_irq(int irq, void *dev_id)
static int jz4740_dma_init(void)
{
+ struct clk *clk;
unsigned int ret;
jz4740_dma_base = ioremap(JZ4740_DMAC_BASE_ADDR, 0x400);
@@ -277,11 +279,29 @@ static int jz4740_dma_init(void)
spin_lock_init(&jz4740_dma_lock);
- ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL);
+ clk = clk_get(NULL, "dma");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ printk(KERN_ERR "JZ4740 DMA: Failed to request clock: %d\n",
+ ret);
+ goto err_iounmap;
+ }
- if (ret)
+ ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL);
+ if (ret) {
printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret);
+ goto err_clkput;
+ }
+
+ clk_prepare_enable(clk);
+
+ return 0;
+
+err_clkput:
+ clk_put(clk);
+err_iounmap:
+ iounmap(jz4740_dma_base);
return ret;
}
arch_initcall(jz4740_dma_init);
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 1/6] MIPS: jz4740: Correct clock gate bit for DMA controller Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 2/6] MIPS: jz4740: Acquire and enable DMA controller clock Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-24 4:59 ` Vinod Koul
2013-05-23 20:36 ` [PATCH 4/6] MIPS: jz4740: Register jz4740 DMA device Lars-Peter Clausen
` (3 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
This patch adds dmaengine support for the JZ4740 DMA controller. For now the
driver will be a wrapper around the custom JZ4740 DMA API. Once all users of the
custom JZ4740 DMA API have been converted to the dmaengine API the custom API
will be removed and direct hardware access will be added to the dmaengine
driver.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/dma/Kconfig | 6 +
drivers/dma/Makefile | 1 +
drivers/dma/dma-jz4740.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 435 insertions(+)
create mode 100644 drivers/dma/dma-jz4740.c
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index e992489..b3e8952 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -312,6 +312,12 @@ config MMP_PDMA
help
Support the MMP PDMA engine for PXA and MMP platfrom.
+config DMA_JZ4740
+ tristate "JZ4740 DMA support"
+ depends on MACH_JZ4740
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index a2b0df5..6127a61 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -38,3 +38,4 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
+obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c
new file mode 100644
index 0000000..210bac0
--- /dev/null
+++ b/drivers/dma/dma-jz4740.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2013, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 DMAC support
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach-jz4740/dma.h>
+
+#include "virt-dma.h"
+
+struct jz4740_dma_sg {
+ dma_addr_t addr;
+ unsigned int len;
+};
+
+struct jz4740_dma_desc {
+ struct virt_dma_desc vdesc;
+
+ enum dma_transfer_direction direction;
+ bool cyclic;
+
+ unsigned int num_sgs;
+ struct jz4740_dma_sg sg[];
+};
+
+struct jz4740_dmaengine_chan {
+ struct virt_dma_chan vchan;
+ struct jz4740_dma_chan *jz_chan;
+
+ struct dma_slave_config config;
+
+ struct jz4740_dma_desc *desc;
+ unsigned int next_sg;
+};
+
+struct jz4740_dma_dev {
+ struct dma_device ddev;
+
+ struct jz4740_dmaengine_chan chan[6];
+};
+
+static struct jz4740_dmaengine_chan *to_jz4740_dma_chan(struct dma_chan *c)
+{
+ return container_of(c, struct jz4740_dmaengine_chan, vchan.chan);
+}
+
+static struct jz4740_dma_desc *to_jz4740_dma_desc(struct virt_dma_desc *vdesc)
+{
+ return container_of(vdesc, struct jz4740_dma_desc, vdesc);
+}
+
+static struct jz4740_dma_desc *jz4740_dma_alloc_desc(unsigned int num_sgs)
+{
+ return kzalloc(sizeof(struct jz4740_dma_desc) +
+ sizeof(struct jz4740_dma_sg) * num_sgs, GFP_ATOMIC);
+}
+
+static enum jz4740_dma_width jz4740_dma_width(enum dma_slave_buswidth width)
+{
+ switch (width) {
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ return JZ4740_DMA_WIDTH_8BIT;
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ return JZ4740_DMA_WIDTH_16BIT;
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ return JZ4740_DMA_WIDTH_32BIT;
+ default:
+ return JZ4740_DMA_WIDTH_32BIT;
+ }
+}
+
+static enum jz4740_dma_transfer_size jz4740_dma_maxburst(u32 maxburst)
+{
+ if (maxburst <= 1)
+ return JZ4740_DMA_TRANSFER_SIZE_1BYTE;
+ else if (maxburst <= 3)
+ return JZ4740_DMA_TRANSFER_SIZE_2BYTE;
+ else if (maxburst <= 15)
+ return JZ4740_DMA_TRANSFER_SIZE_4BYTE;
+ else if (maxburst <= 31)
+ return JZ4740_DMA_TRANSFER_SIZE_16BYTE;
+
+ return JZ4740_DMA_TRANSFER_SIZE_32BYTE;
+}
+
+static int jz4740_dma_slave_config(struct dma_chan *c,
+ const struct dma_slave_config *config)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ struct jz4740_dma_config jzcfg;
+
+ switch (config->direction) {
+ case DMA_MEM_TO_DEV:
+ jzcfg.flags = JZ4740_DMA_SRC_AUTOINC;
+ jzcfg.transfer_size = jz4740_dma_maxburst(config->dst_maxburst);
+ break;
+ case DMA_DEV_TO_MEM:
+ jzcfg.flags = JZ4740_DMA_DST_AUTOINC;
+ jzcfg.transfer_size = jz4740_dma_maxburst(config->src_maxburst);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+
+ jzcfg.src_width = jz4740_dma_width(config->src_addr_width);
+ jzcfg.dst_width = jz4740_dma_width(config->dst_addr_width);
+ jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
+ jzcfg.request_type = config->slave_id;
+
+ chan->config = *config;
+
+ jz4740_dma_configure(chan->jz_chan, &jzcfg);
+
+ return 0;
+}
+
+static int jz4740_dma_terminate_all(struct dma_chan *c)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+ jz4740_dma_disable(chan->jz_chan);
+ chan->desc = NULL;
+ vchan_get_all_descriptors(&chan->vchan, &head);
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+
+ vchan_dma_desc_free_list(&chan->vchan, &head);
+
+ return 0;
+}
+
+static int jz4740_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct dma_slave_config *config = (struct dma_slave_config *)arg;
+
+ switch (cmd) {
+ case DMA_SLAVE_CONFIG:
+ return jz4740_dma_slave_config(chan, config);
+ case DMA_TERMINATE_ALL:
+ return jz4740_dma_terminate_all(chan);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int jz4740_dma_start_transfer(struct jz4740_dmaengine_chan *chan)
+{
+ struct virt_dma_desc *vdesc;
+ struct jz4740_dma_sg *sg;
+
+ jz4740_dma_disable(chan->jz_chan);
+
+ if (!chan->desc) {
+ vdesc = vchan_next_desc(&chan->vchan);
+ if (!vdesc)
+ return 0;
+ chan->desc = to_jz4740_dma_desc(vdesc);
+ chan->next_sg = 0;
+ }
+
+ if (chan->next_sg == chan->desc->num_sgs)
+ chan->next_sg = 0;
+
+ sg = &chan->desc->sg[chan->next_sg];
+
+ if (chan->desc->direction == DMA_MEM_TO_DEV) {
+ jz4740_dma_set_src_addr(chan->jz_chan, sg->addr);
+ jz4740_dma_set_dst_addr(chan->jz_chan, chan->config.dst_addr);
+ } else {
+ jz4740_dma_set_src_addr(chan->jz_chan, chan->config.src_addr);
+ jz4740_dma_set_dst_addr(chan->jz_chan, sg->addr);
+ }
+ jz4740_dma_set_transfer_count(chan->jz_chan, sg->len);
+
+ chan->next_sg++;
+
+ jz4740_dma_enable(chan->jz_chan);
+
+ return 0;
+}
+
+static void jz4740_dma_complete_cb(struct jz4740_dma_chan *jz_chan, int error,
+ void *devid)
+{
+ struct jz4740_dmaengine_chan *chan = devid;
+
+ spin_lock(&chan->vchan.lock);
+ if (chan->desc) {
+ if (chan->desc && chan->desc->cyclic) {
+ vchan_cyclic_callback(&chan->desc->vdesc);
+ } else {
+ if (chan->next_sg == chan->desc->num_sgs) {
+ chan->desc = NULL;
+ vchan_cookie_complete(&chan->desc->vdesc);
+ }
+ }
+ }
+ jz4740_dma_start_transfer(chan);
+ spin_unlock(&chan->vchan.lock);
+}
+
+static void jz4740_dma_issue_pending(struct dma_chan *c)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+ if (vchan_issue_pending(&chan->vchan) && !chan->desc)
+ jz4740_dma_start_transfer(chan);
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+}
+
+static struct dma_async_tx_descriptor *jz4740_dma_prep_slave_sg(
+ struct dma_chan *c, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ struct jz4740_dma_desc *desc;
+ struct scatterlist *sg;
+ unsigned int i;
+
+ desc = jz4740_dma_alloc_desc(sg_len);
+ if (!desc)
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ desc->sg[i].addr = sg_dma_address(sg);
+ desc->sg[i].len = sg_dma_len(sg);
+ }
+
+ desc->num_sgs = sg_len;
+ desc->direction = direction;
+ desc->cyclic = false;
+
+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic(
+ struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ struct jz4740_dma_desc *desc;
+ unsigned int num_periods, i;
+
+ if (buf_len % period_len)
+ return NULL;
+
+ num_periods = buf_len / period_len;
+
+ desc = jz4740_dma_alloc_desc(num_periods);
+ if (!desc)
+ return NULL;
+
+ for (i = 0; i < num_periods; i++) {
+ desc->sg[i].addr = buf_addr;
+ desc->sg[i].len = period_len;
+ buf_addr += period_len;
+ }
+
+ desc->num_sgs = num_periods;
+ desc->direction = direction;
+ desc->cyclic = true;
+
+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
+}
+
+static size_t jz4740_dma_desc_residue(struct jz4740_dmaengine_chan *chan,
+ struct jz4740_dma_desc *desc, unsigned int next_sg)
+{
+ size_t residue = 0;
+ unsigned int i;
+
+ residue = 0;
+
+ for (i = next_sg; i < desc->num_sgs; i++)
+ residue += desc->sg[i].len;
+
+ if (next_sg != 0)
+ residue += jz4740_dma_get_residue(chan->jz_chan);
+
+ return residue;
+}
+
+static enum dma_status jz4740_dma_tx_status(struct dma_chan *c,
+ dma_cookie_t cookie, struct dma_tx_state *state)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ struct virt_dma_desc *vdesc;
+ enum dma_status status;
+ unsigned long flags;
+
+ status = dma_cookie_status(c, cookie, state);
+ if (status == DMA_SUCCESS || !state)
+ return status;
+
+ spin_lock_irqsave(&chan->vchan.lock, flags);
+ vdesc = vchan_find_desc(&chan->vchan, cookie);
+ if (cookie == chan->desc->vdesc.tx.cookie) {
+ state->residue = jz4740_dma_desc_residue(chan, chan->desc,
+ chan->next_sg);
+ } else if (vdesc) {
+ state->residue = jz4740_dma_desc_residue(chan,
+ to_jz4740_dma_desc(vdesc), 0);
+ } else {
+ state->residue = 0;
+ }
+ spin_unlock_irqrestore(&chan->vchan.lock, flags);
+
+ return status;
+}
+
+static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+
+ chan->jz_chan = jz4740_dma_request(chan, NULL);
+ if (!chan->jz_chan)
+ return -EBUSY;
+
+ jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
+
+ return 0;
+}
+
+static void jz4740_dma_free_chan_resources(struct dma_chan *c)
+{
+ struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+
+ vchan_free_chan_resources(&chan->vchan);
+ jz4740_dma_free(chan->jz_chan);
+ chan->jz_chan = NULL;
+}
+
+static void jz4740_dma_desc_free(struct virt_dma_desc *vdesc)
+{
+ kfree(container_of(vdesc, struct jz4740_dma_desc, vdesc));
+}
+
+static int jz4740_dma_probe(struct platform_device *pdev)
+{
+ struct jz4740_dmaengine_chan *chan;
+ struct jz4740_dma_dev *dmadev;
+ struct dma_device *dd;
+ unsigned int i;
+ int ret;
+
+ dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL);
+ if (!dmadev)
+ return -EINVAL;
+
+ dd = &dmadev->ddev;
+
+ dma_cap_set(DMA_SLAVE, dd->cap_mask);
+ dma_cap_set(DMA_CYCLIC, dd->cap_mask);
+ dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources;
+ dd->device_free_chan_resources = jz4740_dma_free_chan_resources;
+ dd->device_tx_status = jz4740_dma_tx_status;
+ dd->device_issue_pending = jz4740_dma_issue_pending;
+ dd->device_prep_slave_sg = jz4740_dma_prep_slave_sg;
+ dd->device_prep_dma_cyclic = jz4740_dma_prep_dma_cyclic;
+ dd->device_control = jz4740_dma_control;
+ dd->dev = &pdev->dev;
+ dd->chancnt = 6;
+ INIT_LIST_HEAD(&dd->channels);
+
+ for (i = 0; i < dd->chancnt; i++) {
+ chan = &dmadev->chan[i];
+ chan->vchan.desc_free = jz4740_dma_desc_free;
+ vchan_init(&chan->vchan, dd);
+ }
+
+ ret = dma_async_device_register(dd);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, dmadev);
+
+ return 0;
+}
+
+static int jz4740_dma_remove(struct platform_device *pdev)
+{
+ struct jz4740_dma_dev *dmadev = platform_get_drvdata(pdev);
+
+ dma_async_device_unregister(&dmadev->ddev);
+
+ return 0;
+}
+
+static struct platform_driver jz4740_dma_driver = {
+ .probe = jz4740_dma_probe,
+ .remove = jz4740_dma_remove,
+ .driver = {
+ .name = "jz4740-dma",
+ .owner = THIS_MODULE,
+ },
+};
+module_platform_driver(jz4740_dma_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("JZ4740 DMA driver");
+MODULE_LICENSE("GPLv2");
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/6] MIPS: jz4740: Register jz4740 DMA device
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
` (2 preceding siblings ...)
2013-05-23 20:36 ` [PATCH 3/6] dma: Add a jz4740 dmaengine driver Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver Lars-Peter Clausen
` (2 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
Register a device for the newly added jz4740 dmaengine driver.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
arch/mips/include/asm/mach-jz4740/platform.h | 1 +
arch/mips/jz4740/board-qi_lb60.c | 1 +
arch/mips/jz4740/platform.c | 21 +++++++++++++++++++++
3 files changed, 23 insertions(+)
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 72cfebd..05988c2 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -32,6 +32,7 @@ extern struct platform_device jz4740_codec_device;
extern struct platform_device jz4740_adc_device;
extern struct platform_device jz4740_wdt_device;
extern struct platform_device jz4740_pwm_device;
+extern struct platform_device jz4740_dma_device;
void jz4740_serial_device_register(void);
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index be2b3de..8a5ec0e 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -438,6 +438,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
&jz4740_rtc_device,
&jz4740_adc_device,
&jz4740_pwm_device,
+ &jz4740_dma_device,
&qi_lb60_gpio_keys,
&qi_lb60_pwm_beeper,
&qi_lb60_charger_device,
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index e9348fd..35a9d8c 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -329,3 +329,24 @@ struct platform_device jz4740_pwm_device = {
.name = "jz4740-pwm",
.id = -1,
};
+
+/* DMA */
+static struct resource jz4740_dma_resources[] = {
+ {
+ .start = JZ4740_DMAC_BASE_ADDR,
+ .end = JZ4740_DMAC_BASE_ADDR + 0x400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = JZ4740_IRQ_DMAC,
+ .end = JZ4740_IRQ_DMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device jz4740_dma_device = {
+ .name = "jz4740-dma",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_dma_resources),
+ .resource = jz4740_dma_resources,
+};
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
` (3 preceding siblings ...)
2013-05-23 20:36 ` [PATCH 4/6] MIPS: jz4740: Register jz4740 DMA device Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-25 15:16 ` Mark Brown
2013-05-23 20:36 ` [PATCH 6/6] MIPS: jz4740: Remove custom DMA API Lars-Peter Clausen
2013-05-29 9:31 ` [PATCH 0/6] Convert JZ4740 to dmaengine Ralf Baechle
6 siblings, 1 reply; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
Since there is a dmaengine driver for the jz4740 DMA controller now we can use
the generic dmaengine PCM driver instead of a custom one.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
sound/soc/jz4740/Kconfig | 1 +
sound/soc/jz4740/jz4740-i2s.c | 48 +++----
sound/soc/jz4740/jz4740-pcm.c | 310 ++----------------------------------------
sound/soc/jz4740/jz4740-pcm.h | 20 ---
4 files changed, 27 insertions(+), 352 deletions(-)
delete mode 100644 sound/soc/jz4740/jz4740-pcm.h
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
index 5351cba..29f76af 100644
--- a/sound/soc/jz4740/Kconfig
+++ b/sound/soc/jz4740/Kconfig
@@ -1,6 +1,7 @@
config SND_JZ4740_SOC
tristate "SoC Audio for Ingenic JZ4740 SoC"
depends on MACH_JZ4740 && SND_SOC
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the JZ4740 I2S interface. You will also need to select the audio
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 4c849a4..47d3b4c 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -29,9 +29,12 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
+#include <sound/dmaengine_pcm.h>
+
+#include <asm/mach-jz4740/dma.h>
#include "jz4740-i2s.h"
-#include "jz4740-pcm.h"
+
#define JZ_REG_AIC_CONF 0x00
#define JZ_REG_AIC_CTRL 0x04
@@ -89,8 +92,8 @@ struct jz4740_i2s {
struct clk *clk_aic;
struct clk *clk_i2s;
- struct jz4740_pcm_config pcm_config_playback;
- struct jz4740_pcm_config pcm_config_capture;
+ struct snd_dmaengine_dai_dma_data playback_dma_data;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
};
static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
@@ -233,8 +236,6 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- enum jz4740_dma_width dma_width;
- struct jz4740_pcm_config *pcm_config;
unsigned int sample_size;
uint32_t ctrl;
@@ -243,11 +244,9 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
sample_size = 0;
- dma_width = JZ4740_DMA_WIDTH_8BIT;
break;
case SNDRV_PCM_FORMAT_S16:
sample_size = 1;
- dma_width = JZ4740_DMA_WIDTH_16BIT;
break;
default:
return -EINVAL;
@@ -260,22 +259,13 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
else
ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
-
- pcm_config = &i2s->pcm_config_playback;
- pcm_config->dma_config.dst_width = dma_width;
-
} else {
ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
-
- pcm_config = &i2s->pcm_config_capture;
- pcm_config->dma_config.src_width = dma_width;
}
jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
- snd_soc_dai_set_dma_data(dai, substream, pcm_config);
-
return 0;
}
@@ -342,25 +332,19 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
{
- struct jz4740_dma_config *dma_config;
+ struct snd_dmaengine_dai_dma_data *dma_data;
/* Playback */
- dma_config = &i2s->pcm_config_playback.dma_config;
- dma_config->src_width = JZ4740_DMA_WIDTH_32BIT;
- dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
- dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
- dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
- dma_config->mode = JZ4740_DMA_MODE_SINGLE;
- i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+ dma_data = &i2s->playback_dma_data;
+ dma_data->maxburst = 16;
+ dma_data->slave_id = JZ4740_DMA_TYPE_AIC_TRANSMIT;
+ dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
/* Capture */
- dma_config = &i2s->pcm_config_capture.dma_config;
- dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT;
- dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
- dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
- dma_config->flags = JZ4740_DMA_DST_AUTOINC;
- dma_config->mode = JZ4740_DMA_MODE_SINGLE;
- i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+ dma_data = &i2s->capture_dma_data;
+ dma_data->maxburst = 16;
+ dma_data->slave_id = JZ4740_DMA_TYPE_AIC_RECEIVE;
+ dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
}
static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
@@ -371,6 +355,8 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
clk_prepare_enable(i2s->clk_aic);
jz4740_i2c_init_pcm_config(i2s);
+ dai->playback_dma_data = &i2s->playback_dma_data;
+ dai->capture_dma_data = &i2s->capture_dma_data;
conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index 7100592..79fcade 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -19,38 +19,14 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/dma-mapping.h>
+#include <sound/dmaengine_pcm.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/mach-jz4740/dma.h>
-#include "jz4740-pcm.h"
-
-struct jz4740_runtime_data {
- unsigned long dma_period;
- dma_addr_t dma_start;
- dma_addr_t dma_pos;
- dma_addr_t dma_end;
-
- struct jz4740_dma_chan *dma;
-
- dma_addr_t fifo_addr;
-};
-
-/* identify hardware playback capabilities */
static const struct snd_pcm_hardware jz4740_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
-
- .rates = SNDRV_PCM_RATE_8000_48000,
- .channels_min = 1,
- .channels_max = 2,
.period_bytes_min = 16,
.period_bytes_max = 2 * PAGE_SIZE,
.periods_min = 2,
@@ -59,290 +35,22 @@ static const struct snd_pcm_hardware jz4740_pcm_hardware = {
.fifo_size = 32,
};
-static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
- struct snd_pcm_substream *substream)
-{
- unsigned long count;
-
- if (prtd->dma_pos == prtd->dma_end)
- prtd->dma_pos = prtd->dma_start;
-
- if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
- count = prtd->dma_end - prtd->dma_pos;
- else
- count = prtd->dma_period;
-
- jz4740_dma_disable(prtd->dma);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
- jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
- } else {
- jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
- jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
- }
-
- jz4740_dma_set_transfer_count(prtd->dma, count);
-
- prtd->dma_pos += count;
-
- jz4740_dma_enable(prtd->dma);
-}
-
-static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
- void *dev_id)
-{
- struct snd_pcm_substream *substream = dev_id;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd = runtime->private_data;
-
- snd_pcm_period_elapsed(substream);
-
- jz4740_pcm_start_transfer(prtd, substream);
-}
-
-static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct jz4740_pcm_config *config;
-
- config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
- if (!config)
- return 0;
-
- if (!prtd->dma) {
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- prtd->dma = jz4740_dma_request(substream, "PCM Capture");
- else
- prtd->dma = jz4740_dma_request(substream, "PCM Playback");
- }
-
- if (!prtd->dma)
- return -EBUSY;
-
- jz4740_dma_configure(prtd->dma, &config->dma_config);
- prtd->fifo_addr = config->fifo_addr;
-
- jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->dma_period = params_period_bytes(params);
- prtd->dma_start = runtime->dma_addr;
- prtd->dma_pos = prtd->dma_start;
- prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
-
- return 0;
-}
-
-static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
- snd_pcm_set_runtime_buffer(substream, NULL);
- if (prtd->dma) {
- jz4740_dma_free(prtd->dma);
- prtd->dma = NULL;
- }
-
- return 0;
-}
-
-static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
- if (!prtd->dma)
- return -EBUSY;
-
- prtd->dma_pos = prtd->dma_start;
-
- return 0;
-}
-
-static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- jz4740_pcm_start_transfer(prtd, substream);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- jz4740_dma_disable(prtd->dma);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd = runtime->private_data;
- unsigned long byte_offset;
- snd_pcm_uframes_t offset;
- struct jz4740_dma_chan *dma = prtd->dma;
-
- /* prtd->dma_pos points to the end of the current transfer. So by
- * subtracting prdt->dma_start we get the offset to the end of the
- * current period in bytes. By subtracting the residue of the transfer
- * we get the current offset in bytes. */
- byte_offset = prtd->dma_pos - prtd->dma_start;
- byte_offset -= jz4740_dma_get_residue(dma);
-
- offset = bytes_to_frames(runtime, byte_offset);
- if (offset >= runtime->buffer_size)
- offset = 0;
-
- return offset;
-}
-
-static int jz4740_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd;
-
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
- if (prtd == NULL)
- return -ENOMEM;
-
- snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
-
- runtime->private_data = prtd;
-
- return 0;
-}
-
-static int jz4740_pcm_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct jz4740_runtime_data *prtd = runtime->private_data;
-
- kfree(prtd);
-
- return 0;
-}
-
-static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-static struct snd_pcm_ops jz4740_pcm_ops = {
- .open = jz4740_pcm_open,
- .close = jz4740_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = jz4740_pcm_hw_params,
- .hw_free = jz4740_pcm_hw_free,
- .prepare = jz4740_pcm_prepare,
- .trigger = jz4740_pcm_trigger,
- .pointer = jz4740_pcm_pointer,
- .mmap = jz4740_pcm_mmap,
-};
-
-static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = jz4740_pcm_hardware.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
-
- buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
-
- return 0;
-}
-
-static void jz4740_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area,
- buf->addr);
- buf->area = NULL;
- }
-}
-
-static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
-
-static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_pcm *pcm = rtd->pcm;
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &jz4740_pcm_dmamask;
-
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
- ret = jz4740_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto err;
- }
-
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- ret = jz4740_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto err;
- }
-
-err:
- return ret;
-}
-
-static struct snd_soc_platform_driver jz4740_soc_platform = {
- .ops = &jz4740_pcm_ops,
- .pcm_new = jz4740_pcm_new,
- .pcm_free = jz4740_pcm_free,
+static const struct snd_dmaengine_pcm_config jz4740_dmaengine_pcm_config = {
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+ .pcm_hardware = &jz4740_pcm_hardware,
+ .prealloc_buffer_size = 256 * PAGE_SIZE,
};
static int jz4740_pcm_probe(struct platform_device *pdev)
{
- return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
+ return snd_dmaengine_pcm_register(&pdev->dev,
+ &jz4740_dmaengine_pcm_config,
+ SND_DMAENGINE_PCM_FLAG_COMPAT);
}
static int jz4740_pcm_remove(struct platform_device *pdev)
{
- snd_soc_unregister_platform(&pdev->dev);
+ snd_dmaengine_pcm_unregister(&pdev->dev);
return 0;
}
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
deleted file mode 100644
index 1220cbb..0000000
--- a/sound/soc/jz4740/jz4740-pcm.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _JZ4740_PCM_H
-#define _JZ4740_PCM_H
-
-#include <linux/dma-mapping.h>
-#include <asm/mach-jz4740/dma.h>
-
-
-struct jz4740_pcm_config {
- struct jz4740_dma_config dma_config;
- phys_addr_t fifo_addr;
-};
-
-#endif
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/6] MIPS: jz4740: Remove custom DMA API
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
` (4 preceding siblings ...)
2013-05-23 20:36 ` [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver Lars-Peter Clausen
@ 2013-05-23 20:36 ` Lars-Peter Clausen
2013-05-29 9:31 ` [PATCH 0/6] Convert JZ4740 to dmaengine Ralf Baechle
6 siblings, 0 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-23 20:36 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
Now that all users of the custom jz4740 DMA API have been converted to use
the dmaengine API instead we can remove the custom API and move all the code
talking to the hardware to the dmaengine driver.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
arch/mips/include/asm/mach-jz4740/dma.h | 56 ------
arch/mips/jz4740/Makefile | 2 +-
arch/mips/jz4740/dma.c | 307 --------------------------------
drivers/dma/dma-jz4740.c | 268 +++++++++++++++++++++++-----
4 files changed, 229 insertions(+), 404 deletions(-)
delete mode 100644 arch/mips/jz4740/dma.c
diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h
index 98b4e7c..509cd58 100644
--- a/arch/mips/include/asm/mach-jz4740/dma.h
+++ b/arch/mips/include/asm/mach-jz4740/dma.h
@@ -16,8 +16,6 @@
#ifndef __ASM_MACH_JZ4740_DMA_H__
#define __ASM_MACH_JZ4740_DMA_H__
-struct jz4740_dma_chan;
-
enum jz4740_dma_request_type {
JZ4740_DMA_TYPE_AUTO_REQUEST = 8,
JZ4740_DMA_TYPE_UART_TRANSMIT = 20,
@@ -33,58 +31,4 @@ enum jz4740_dma_request_type {
JZ4740_DMA_TYPE_SLCD = 30,
};
-enum jz4740_dma_width {
- JZ4740_DMA_WIDTH_32BIT = 0,
- JZ4740_DMA_WIDTH_8BIT = 1,
- JZ4740_DMA_WIDTH_16BIT = 2,
-};
-
-enum jz4740_dma_transfer_size {
- JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0,
- JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1,
- JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2,
- JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3,
- JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4,
-};
-
-enum jz4740_dma_flags {
- JZ4740_DMA_SRC_AUTOINC = 0x2,
- JZ4740_DMA_DST_AUTOINC = 0x1,
-};
-
-enum jz4740_dma_mode {
- JZ4740_DMA_MODE_SINGLE = 0,
- JZ4740_DMA_MODE_BLOCK = 1,
-};
-
-struct jz4740_dma_config {
- enum jz4740_dma_width src_width;
- enum jz4740_dma_width dst_width;
- enum jz4740_dma_transfer_size transfer_size;
- enum jz4740_dma_request_type request_type;
- enum jz4740_dma_flags flags;
- enum jz4740_dma_mode mode;
-};
-
-typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int, void *);
-
-struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name);
-void jz4740_dma_free(struct jz4740_dma_chan *dma);
-
-void jz4740_dma_configure(struct jz4740_dma_chan *dma,
- const struct jz4740_dma_config *config);
-
-
-void jz4740_dma_enable(struct jz4740_dma_chan *dma);
-void jz4740_dma_disable(struct jz4740_dma_chan *dma);
-
-void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src);
-void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst);
-void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count);
-
-uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma);
-
-void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
- jz4740_dma_complete_callback_t cb);
-
#endif /* __ASM_JZ4740_DMA_H__ */
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 63bad0e..28e5535 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -4,7 +4,7 @@
# Object file lists.
-obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
+obj-y += prom.o irq.o time.o reset.o setup.o \
gpio.o clock.o platform.o timer.o serial.o
obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c
deleted file mode 100644
index 0e34b97..0000000
--- a/arch/mips/jz4740/dma.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 SoC DMA support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-
-#include <linux/dma-mapping.h>
-#include <asm/mach-jz4740/dma.h>
-#include <asm/mach-jz4740/base.h>
-
-#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20)
-#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20)
-#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20)
-#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20)
-#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20)
-#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20)
-#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20)
-
-#define JZ_REG_DMA_CTRL 0x300
-#define JZ_REG_DMA_IRQ 0x304
-#define JZ_REG_DMA_DOORBELL 0x308
-#define JZ_REG_DMA_DOORBELL_SET 0x30C
-
-#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31)
-#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6)
-#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4)
-#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3)
-#define JZ_DMA_STATUS_CTRL_HALT BIT(2)
-#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1)
-#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0)
-
-#define JZ_DMA_CMD_SRC_INC BIT(23)
-#define JZ_DMA_CMD_DST_INC BIT(22)
-#define JZ_DMA_CMD_RDIL_MASK (0xf << 16)
-#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14)
-#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12)
-#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8)
-#define JZ_DMA_CMD_BLOCK_MODE BIT(7)
-#define JZ_DMA_CMD_DESC_VALID BIT(4)
-#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3)
-#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2)
-#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1)
-#define JZ_DMA_CMD_LINK_ENABLE BIT(0)
-
-#define JZ_DMA_CMD_FLAGS_OFFSET 22
-#define JZ_DMA_CMD_RDIL_OFFSET 16
-#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14
-#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12
-#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8
-#define JZ_DMA_CMD_MODE_OFFSET 7
-
-#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8)
-#define JZ_DMA_CTRL_HALT BIT(3)
-#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2)
-#define JZ_DMA_CTRL_ENABLE BIT(0)
-
-
-static void __iomem *jz4740_dma_base;
-static spinlock_t jz4740_dma_lock;
-
-static inline uint32_t jz4740_dma_read(size_t reg)
-{
- return readl(jz4740_dma_base + reg);
-}
-
-static inline void jz4740_dma_write(size_t reg, uint32_t val)
-{
- writel(val, jz4740_dma_base + reg);
-}
-
-static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask)
-{
- uint32_t val2;
- val2 = jz4740_dma_read(reg);
- val2 &= ~mask;
- val2 |= val;
- jz4740_dma_write(reg, val2);
-}
-
-struct jz4740_dma_chan {
- unsigned int id;
- void *dev;
- const char *name;
-
- enum jz4740_dma_flags flags;
- uint32_t transfer_shift;
-
- jz4740_dma_complete_callback_t complete_cb;
-
- unsigned used:1;
-};
-
-#define JZ4740_DMA_CHANNEL(_id) { .id = _id }
-
-struct jz4740_dma_chan jz4740_dma_channels[] = {
- JZ4740_DMA_CHANNEL(0),
- JZ4740_DMA_CHANNEL(1),
- JZ4740_DMA_CHANNEL(2),
- JZ4740_DMA_CHANNEL(3),
- JZ4740_DMA_CHANNEL(4),
- JZ4740_DMA_CHANNEL(5),
-};
-
-struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name)
-{
- unsigned int i;
- struct jz4740_dma_chan *dma = NULL;
-
- spin_lock(&jz4740_dma_lock);
-
- for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) {
- if (!jz4740_dma_channels[i].used) {
- dma = &jz4740_dma_channels[i];
- dma->used = 1;
- break;
- }
- }
-
- spin_unlock(&jz4740_dma_lock);
-
- if (!dma)
- return NULL;
-
- dma->dev = dev;
- dma->name = name;
-
- return dma;
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_request);
-
-void jz4740_dma_configure(struct jz4740_dma_chan *dma,
- const struct jz4740_dma_config *config)
-{
- uint32_t cmd;
-
- switch (config->transfer_size) {
- case JZ4740_DMA_TRANSFER_SIZE_2BYTE:
- dma->transfer_shift = 1;
- break;
- case JZ4740_DMA_TRANSFER_SIZE_4BYTE:
- dma->transfer_shift = 2;
- break;
- case JZ4740_DMA_TRANSFER_SIZE_16BYTE:
- dma->transfer_shift = 4;
- break;
- case JZ4740_DMA_TRANSFER_SIZE_32BYTE:
- dma->transfer_shift = 5;
- break;
- default:
- dma->transfer_shift = 0;
- break;
- }
-
- cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET;
- cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET;
- cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET;
- cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET;
- cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET;
- cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE;
-
- jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd);
- jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), 0);
- jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_configure);
-
-void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src)
-{
- jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr);
-
-void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst)
-{
- jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr);
-
-void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count)
-{
- count >>= dma->transfer_shift;
- jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count);
-
-void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
- jz4740_dma_complete_callback_t cb)
-{
- dma->complete_cb = cb;
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb);
-
-void jz4740_dma_free(struct jz4740_dma_chan *dma)
-{
- dma->dev = NULL;
- dma->complete_cb = NULL;
- dma->used = 0;
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_free);
-
-void jz4740_dma_enable(struct jz4740_dma_chan *dma)
-{
- jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id),
- JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE,
- JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC |
- JZ_DMA_STATUS_CTRL_ENABLE);
-
- jz4740_dma_write_mask(JZ_REG_DMA_CTRL,
- JZ_DMA_CTRL_ENABLE,
- JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_enable);
-
-void jz4740_dma_disable(struct jz4740_dma_chan *dma)
-{
- jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
- JZ_DMA_STATUS_CTRL_ENABLE);
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_disable);
-
-uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma)
-{
- uint32_t residue;
- residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id));
- return residue << dma->transfer_shift;
-}
-EXPORT_SYMBOL_GPL(jz4740_dma_get_residue);
-
-static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma)
-{
- (void) jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
-
- jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
- JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
-
- if (dma->complete_cb)
- dma->complete_cb(dma, 0, dma->dev);
-}
-
-static irqreturn_t jz4740_dma_irq(int irq, void *dev_id)
-{
- uint32_t irq_status;
- unsigned int i;
-
- irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ);
-
- for (i = 0; i < 6; ++i) {
- if (irq_status & (1 << i))
- jz4740_dma_chan_irq(&jz4740_dma_channels[i]);
- }
-
- return IRQ_HANDLED;
-}
-
-static int jz4740_dma_init(void)
-{
- struct clk *clk;
- unsigned int ret;
-
- jz4740_dma_base = ioremap(JZ4740_DMAC_BASE_ADDR, 0x400);
-
- if (!jz4740_dma_base)
- return -EBUSY;
-
- spin_lock_init(&jz4740_dma_lock);
-
- clk = clk_get(NULL, "dma");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- printk(KERN_ERR "JZ4740 DMA: Failed to request clock: %d\n",
- ret);
- goto err_iounmap;
- }
-
- ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL);
- if (ret) {
- printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret);
- goto err_clkput;
- }
-
- clk_prepare_enable(clk);
-
- return 0;
-
-err_clkput:
- clk_put(clk);
-
-err_iounmap:
- iounmap(jz4740_dma_base);
- return ret;
-}
-arch_initcall(jz4740_dma_init);
diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c
index 210bac0..a57cfdc 100644
--- a/drivers/dma/dma-jz4740.c
+++ b/drivers/dma/dma-jz4740.c
@@ -22,11 +22,83 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
#include <asm/mach-jz4740/dma.h>
#include "virt-dma.h"
+#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20)
+#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20)
+#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20)
+#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20)
+#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20)
+#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20)
+#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20)
+
+#define JZ_REG_DMA_CTRL 0x300
+#define JZ_REG_DMA_IRQ 0x304
+#define JZ_REG_DMA_DOORBELL 0x308
+#define JZ_REG_DMA_DOORBELL_SET 0x30C
+
+#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31)
+#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6)
+#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4)
+#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3)
+#define JZ_DMA_STATUS_CTRL_HALT BIT(2)
+#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1)
+#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0)
+
+#define JZ_DMA_CMD_SRC_INC BIT(23)
+#define JZ_DMA_CMD_DST_INC BIT(22)
+#define JZ_DMA_CMD_RDIL_MASK (0xf << 16)
+#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14)
+#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12)
+#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8)
+#define JZ_DMA_CMD_BLOCK_MODE BIT(7)
+#define JZ_DMA_CMD_DESC_VALID BIT(4)
+#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3)
+#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2)
+#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1)
+#define JZ_DMA_CMD_LINK_ENABLE BIT(0)
+
+#define JZ_DMA_CMD_FLAGS_OFFSET 22
+#define JZ_DMA_CMD_RDIL_OFFSET 16
+#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14
+#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12
+#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8
+#define JZ_DMA_CMD_MODE_OFFSET 7
+
+#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8)
+#define JZ_DMA_CTRL_HALT BIT(3)
+#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2)
+#define JZ_DMA_CTRL_ENABLE BIT(0)
+
+enum jz4740_dma_width {
+ JZ4740_DMA_WIDTH_32BIT = 0,
+ JZ4740_DMA_WIDTH_8BIT = 1,
+ JZ4740_DMA_WIDTH_16BIT = 2,
+};
+
+enum jz4740_dma_transfer_size {
+ JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0,
+ JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1,
+ JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2,
+ JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3,
+ JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4,
+};
+
+enum jz4740_dma_flags {
+ JZ4740_DMA_SRC_AUTOINC = 0x2,
+ JZ4740_DMA_DST_AUTOINC = 0x1,
+};
+
+enum jz4740_dma_mode {
+ JZ4740_DMA_MODE_SINGLE = 0,
+ JZ4740_DMA_MODE_BLOCK = 1,
+};
+
struct jz4740_dma_sg {
dma_addr_t addr;
unsigned int len;
@@ -44,9 +116,10 @@ struct jz4740_dma_desc {
struct jz4740_dmaengine_chan {
struct virt_dma_chan vchan;
- struct jz4740_dma_chan *jz_chan;
+ unsigned int id;
struct dma_slave_config config;
+ unsigned int transfer_shift;
struct jz4740_dma_desc *desc;
unsigned int next_sg;
@@ -54,10 +127,19 @@ struct jz4740_dmaengine_chan {
struct jz4740_dma_dev {
struct dma_device ddev;
+ void __iomem *base;
+ struct clk *clk;
struct jz4740_dmaengine_chan chan[6];
};
+static struct jz4740_dma_dev *jz4740_dma_chan_get_dev(
+ struct jz4740_dmaengine_chan *chan)
+{
+ return container_of(chan->vchan.chan.device, struct jz4740_dma_dev,
+ ddev);
+}
+
static struct jz4740_dmaengine_chan *to_jz4740_dma_chan(struct dma_chan *c)
{
return container_of(c, struct jz4740_dmaengine_chan, vchan.chan);
@@ -68,6 +150,29 @@ static struct jz4740_dma_desc *to_jz4740_dma_desc(struct virt_dma_desc *vdesc)
return container_of(vdesc, struct jz4740_dma_desc, vdesc);
}
+static inline uint32_t jz4740_dma_read(struct jz4740_dma_dev *dmadev,
+ unsigned int reg)
+{
+ return readl(dmadev->base + reg);
+}
+
+static inline void jz4740_dma_write(struct jz4740_dma_dev *dmadev,
+ unsigned reg, uint32_t val)
+{
+ writel(val, dmadev->base + reg);
+}
+
+static inline void jz4740_dma_write_mask(struct jz4740_dma_dev *dmadev,
+ unsigned int reg, uint32_t val, uint32_t mask)
+{
+ uint32_t tmp;
+
+ tmp = jz4740_dma_read(dmadev, reg);
+ tmp &= ~mask;
+ tmp |= val;
+ jz4740_dma_write(dmadev, reg, tmp);
+}
+
static struct jz4740_dma_desc *jz4740_dma_alloc_desc(unsigned int num_sgs)
{
return kzalloc(sizeof(struct jz4740_dma_desc) +
@@ -106,30 +211,60 @@ static int jz4740_dma_slave_config(struct dma_chan *c,
const struct dma_slave_config *config)
{
struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
- struct jz4740_dma_config jzcfg;
+ struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan);
+ enum jz4740_dma_width src_width;
+ enum jz4740_dma_width dst_width;
+ enum jz4740_dma_transfer_size transfer_size;
+ enum jz4740_dma_flags flags;
+ uint32_t cmd;
switch (config->direction) {
case DMA_MEM_TO_DEV:
- jzcfg.flags = JZ4740_DMA_SRC_AUTOINC;
- jzcfg.transfer_size = jz4740_dma_maxburst(config->dst_maxburst);
+ flags = JZ4740_DMA_SRC_AUTOINC;
+ transfer_size = jz4740_dma_maxburst(config->dst_maxburst);
break;
case DMA_DEV_TO_MEM:
- jzcfg.flags = JZ4740_DMA_DST_AUTOINC;
- jzcfg.transfer_size = jz4740_dma_maxburst(config->src_maxburst);
+ flags = JZ4740_DMA_DST_AUTOINC;
+ transfer_size = jz4740_dma_maxburst(config->src_maxburst);
break;
default:
return -EINVAL;
}
-
- jzcfg.src_width = jz4740_dma_width(config->src_addr_width);
- jzcfg.dst_width = jz4740_dma_width(config->dst_addr_width);
- jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
- jzcfg.request_type = config->slave_id;
+ src_width = jz4740_dma_width(config->src_addr_width);
+ dst_width = jz4740_dma_width(config->dst_addr_width);
chan->config = *config;
- jz4740_dma_configure(chan->jz_chan, &jzcfg);
+ switch (transfer_size) {
+ case JZ4740_DMA_TRANSFER_SIZE_2BYTE:
+ chan->transfer_shift = 1;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_4BYTE:
+ chan->transfer_shift = 2;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_16BYTE:
+ chan->transfer_shift = 4;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_32BYTE:
+ chan->transfer_shift = 5;
+ break;
+ default:
+ chan->transfer_shift = 0;
+ break;
+ }
+
+ cmd = flags << JZ_DMA_CMD_FLAGS_OFFSET;
+ cmd |= src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET;
+ cmd |= dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET;
+ cmd |= transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET;
+ cmd |= JZ4740_DMA_MODE_SINGLE << JZ_DMA_CMD_MODE_OFFSET;
+ cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE;
+
+ jz4740_dma_write(dmadev, JZ_REG_DMA_CMD(chan->id), cmd);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_REQ_TYPE(chan->id),
+ config->slave_id);
return 0;
}
@@ -137,11 +272,13 @@ static int jz4740_dma_slave_config(struct dma_chan *c,
static int jz4740_dma_terminate_all(struct dma_chan *c)
{
struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
+ struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan);
unsigned long flags;
LIST_HEAD(head);
spin_lock_irqsave(&chan->vchan.lock, flags);
- jz4740_dma_disable(chan->jz_chan);
+ jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0,
+ JZ_DMA_STATUS_CTRL_ENABLE);
chan->desc = NULL;
vchan_get_all_descriptors(&chan->vchan, &head);
spin_unlock_irqrestore(&chan->vchan.lock, flags);
@@ -168,10 +305,12 @@ static int jz4740_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
static int jz4740_dma_start_transfer(struct jz4740_dmaengine_chan *chan)
{
+ struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan);
struct virt_dma_desc *vdesc;
struct jz4740_dma_sg *sg;
- jz4740_dma_disable(chan->jz_chan);
+ jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0,
+ JZ_DMA_STATUS_CTRL_ENABLE);
if (!chan->desc) {
vdesc = vchan_next_desc(&chan->vchan);
@@ -187,26 +326,35 @@ static int jz4740_dma_start_transfer(struct jz4740_dmaengine_chan *chan)
sg = &chan->desc->sg[chan->next_sg];
if (chan->desc->direction == DMA_MEM_TO_DEV) {
- jz4740_dma_set_src_addr(chan->jz_chan, sg->addr);
- jz4740_dma_set_dst_addr(chan->jz_chan, chan->config.dst_addr);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_SRC_ADDR(chan->id),
+ sg->addr);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_DST_ADDR(chan->id),
+ chan->config.dst_addr);
} else {
- jz4740_dma_set_src_addr(chan->jz_chan, chan->config.src_addr);
- jz4740_dma_set_dst_addr(chan->jz_chan, sg->addr);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_SRC_ADDR(chan->id),
+ chan->config.src_addr);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_DST_ADDR(chan->id),
+ sg->addr);
}
- jz4740_dma_set_transfer_count(chan->jz_chan, sg->len);
+ jz4740_dma_write(dmadev, JZ_REG_DMA_TRANSFER_COUNT(chan->id),
+ sg->len >> chan->transfer_shift);
chan->next_sg++;
- jz4740_dma_enable(chan->jz_chan);
+ jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id),
+ JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE,
+ JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC |
+ JZ_DMA_STATUS_CTRL_ENABLE);
+
+ jz4740_dma_write_mask(dmadev, JZ_REG_DMA_CTRL,
+ JZ_DMA_CTRL_ENABLE,
+ JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE);
return 0;
}
-static void jz4740_dma_complete_cb(struct jz4740_dma_chan *jz_chan, int error,
- void *devid)
+static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan)
{
- struct jz4740_dmaengine_chan *chan = devid;
-
spin_lock(&chan->vchan.lock);
if (chan->desc) {
if (chan->desc && chan->desc->cyclic) {
@@ -222,6 +370,28 @@ static void jz4740_dma_complete_cb(struct jz4740_dma_chan *jz_chan, int error,
spin_unlock(&chan->vchan.lock);
}
+static irqreturn_t jz4740_dma_irq(int irq, void *devid)
+{
+ struct jz4740_dma_dev *dmadev = devid;
+ uint32_t irq_status;
+ unsigned int i;
+
+ irq_status = readl(dmadev->base + JZ_REG_DMA_IRQ);
+
+ for (i = 0; i < 6; ++i) {
+ if (irq_status & (1 << i)) {
+ jz4740_dma_write_mask(dmadev,
+ JZ_REG_DMA_STATUS_CTRL(i), 0,
+ JZ_DMA_STATUS_CTRL_ENABLE |
+ JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
+
+ jz4740_dma_chan_irq(&dmadev->chan[i]);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
static void jz4740_dma_issue_pending(struct dma_chan *c)
{
struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
@@ -293,7 +463,8 @@ static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic(
static size_t jz4740_dma_desc_residue(struct jz4740_dmaengine_chan *chan,
struct jz4740_dma_desc *desc, unsigned int next_sg)
{
- size_t residue = 0;
+ struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan);
+ unsigned int residue, count;
unsigned int i;
residue = 0;
@@ -301,8 +472,11 @@ static size_t jz4740_dma_desc_residue(struct jz4740_dmaengine_chan *chan,
for (i = next_sg; i < desc->num_sgs; i++)
residue += desc->sg[i].len;
- if (next_sg != 0)
- residue += jz4740_dma_get_residue(chan->jz_chan);
+ if (next_sg != 0) {
+ count = jz4740_dma_read(dmadev,
+ JZ_REG_DMA_TRANSFER_COUNT(chan->id));
+ residue += count << chan->transfer_shift;
+ }
return residue;
}
@@ -337,24 +511,12 @@ static enum dma_status jz4740_dma_tx_status(struct dma_chan *c,
static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
{
- struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
-
- chan->jz_chan = jz4740_dma_request(chan, NULL);
- if (!chan->jz_chan)
- return -EBUSY;
-
- jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
-
return 0;
}
static void jz4740_dma_free_chan_resources(struct dma_chan *c)
{
- struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
-
- vchan_free_chan_resources(&chan->vchan);
- jz4740_dma_free(chan->jz_chan);
- chan->jz_chan = NULL;
+ vchan_free_chan_resources(to_virt_chan(c));
}
static void jz4740_dma_desc_free(struct virt_dma_desc *vdesc)
@@ -368,7 +530,9 @@ static int jz4740_dma_probe(struct platform_device *pdev)
struct jz4740_dma_dev *dmadev;
struct dma_device *dd;
unsigned int i;
+ struct resource *res;
int ret;
+ int irq;
dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL);
if (!dmadev)
@@ -376,6 +540,17 @@ static int jz4740_dma_probe(struct platform_device *pdev)
dd = &dmadev->ddev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dmadev->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dmadev->base))
+ return PTR_ERR(dmadev->base);
+
+ dmadev->clk = clk_get(&pdev->dev, "dma");
+ if (IS_ERR(dmadev->clk))
+ return PTR_ERR(dmadev->clk);
+
+ clk_prepare_enable(dmadev->clk);
+
dma_cap_set(DMA_SLAVE, dd->cap_mask);
dma_cap_set(DMA_CYCLIC, dd->cap_mask);
dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources;
@@ -391,6 +566,7 @@ static int jz4740_dma_probe(struct platform_device *pdev)
for (i = 0; i < dd->chancnt; i++) {
chan = &dmadev->chan[i];
+ chan->id = i;
chan->vchan.desc_free = jz4740_dma_desc_free;
vchan_init(&chan->vchan, dd);
}
@@ -399,16 +575,28 @@ static int jz4740_dma_probe(struct platform_device *pdev)
if (ret)
return ret;
+ irq = platform_get_irq(pdev, 0);
+ ret = request_irq(irq, jz4740_dma_irq, 0, dev_name(&pdev->dev), dmadev);
+ if (ret)
+ goto err_unregister;
+
platform_set_drvdata(pdev, dmadev);
return 0;
+
+err_unregister:
+ dma_async_device_unregister(dd);
+ return ret;
}
static int jz4740_dma_remove(struct platform_device *pdev)
{
struct jz4740_dma_dev *dmadev = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+ free_irq(irq, dmadev);
dma_async_device_unregister(&dmadev->ddev);
+ clk_disable_unprepare(dmadev->clk);
return 0;
}
--
1.8.2.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-23 20:36 ` [PATCH 3/6] dma: Add a jz4740 dmaengine driver Lars-Peter Clausen
@ 2013-05-24 4:59 ` Vinod Koul
2013-05-24 5:58 ` Lars-Peter Clausen
0 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2013-05-24 4:59 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On Thu, May 23, 2013 at 10:36:24PM +0200, Lars-Peter Clausen wrote:
> This patch adds dmaengine support for the JZ4740 DMA controller. For now the
> driver will be a wrapper around the custom JZ4740 DMA API. Once all users of the
> custom JZ4740 DMA API have been converted to the dmaengine API the custom API
> will be removed and direct hardware access will be added to the dmaengine
> driver.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> +static enum jz4740_dma_width jz4740_dma_width(enum dma_slave_buswidth width)
> +{
> + switch (width) {
> + case DMA_SLAVE_BUSWIDTH_1_BYTE:
> + return JZ4740_DMA_WIDTH_8BIT;
> + case DMA_SLAVE_BUSWIDTH_2_BYTES:
> + return JZ4740_DMA_WIDTH_16BIT;
> + case DMA_SLAVE_BUSWIDTH_4_BYTES:
> + return JZ4740_DMA_WIDTH_32BIT;
> + default:
> + return JZ4740_DMA_WIDTH_32BIT;
> + }
Only diff between the values here and dmaengien values is JZ4740_DMA_WIDTH_32BIT
as 0. But the header tells me taht its default and SIZE one has values in that
pattern too. If that is the case you maybe able to get rid on conversion and use
dmaengine values directly.
> +}
> +
> +static enum jz4740_dma_transfer_size jz4740_dma_maxburst(u32 maxburst)
> +{
> + if (maxburst <= 1)
> + return JZ4740_DMA_TRANSFER_SIZE_1BYTE;
> + else if (maxburst <= 3)
> + return JZ4740_DMA_TRANSFER_SIZE_2BYTE;
> + else if (maxburst <= 15)
> + return JZ4740_DMA_TRANSFER_SIZE_4BYTE;
> + else if (maxburst <= 31)
> + return JZ4740_DMA_TRANSFER_SIZE_16BYTE;
> +
> + return JZ4740_DMA_TRANSFER_SIZE_32BYTE;
> +}
> +
> +static int jz4740_dma_slave_config(struct dma_chan *c,
> + const struct dma_slave_config *config)
> +{
> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> + struct jz4740_dma_config jzcfg;
> +
> + switch (config->direction) {
> + case DMA_MEM_TO_DEV:
> + jzcfg.flags = JZ4740_DMA_SRC_AUTOINC;
> + jzcfg.transfer_size = jz4740_dma_maxburst(config->dst_maxburst);
> + break;
> + case DMA_DEV_TO_MEM:
> + jzcfg.flags = JZ4740_DMA_DST_AUTOINC;
> + jzcfg.transfer_size = jz4740_dma_maxburst(config->src_maxburst);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> +
> + jzcfg.src_width = jz4740_dma_width(config->src_addr_width);
> + jzcfg.dst_width = jz4740_dma_width(config->dst_addr_width);
this should be direction based, typically DMA engines have only one width to be
programmed.
> + jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
> + jzcfg.request_type = config->slave_id;
> +
> + chan->config = *config;
> +
> + jz4740_dma_configure(chan->jz_chan, &jzcfg);
> +
> + return 0;
You are NOT use src_addr/dstn_addr? How else are you passing the periphral
address?
> +}
> +
> +static int jz4740_dma_terminate_all(struct dma_chan *c)
> +{
> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> + unsigned long flags;
> + LIST_HEAD(head);
> +
> + spin_lock_irqsave(&chan->vchan.lock, flags);
> + jz4740_dma_disable(chan->jz_chan);
> + chan->desc = NULL;
> + vchan_get_all_descriptors(&chan->vchan, &head);
> + spin_unlock_irqrestore(&chan->vchan.lock, flags);
> +
> + vchan_dma_desc_free_list(&chan->vchan, &head);
> +
> + return 0;
> +}
> +
> +static int jz4740_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
> + unsigned long arg)
> +{
> + struct dma_slave_config *config = (struct dma_slave_config *)arg;
> +
> + switch (cmd) {
> + case DMA_SLAVE_CONFIG:
> + return jz4740_dma_slave_config(chan, config);
> + case DMA_TERMINATE_ALL:
> + return jz4740_dma_terminate_all(chan);
> + default:
> + return -EINVAL;
ENXIO/ENOSYS perhaps?
> + }
> +}
> +
> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
> +{
> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> +
> + chan->jz_chan = jz4740_dma_request(chan, NULL);
> + if (!chan->jz_chan)
> + return -EBUSY;
> +
> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
> +
> + return 0;
Zero is not expected value, you need to return the descriptors allocated
sucessfully.
> +}
> +
> +static void jz4740_dma_free_chan_resources(struct dma_chan *c)
> +{
> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> +
> + vchan_free_chan_resources(&chan->vchan);
> + jz4740_dma_free(chan->jz_chan);
> + chan->jz_chan = NULL;
> +}
> +
> +static void jz4740_dma_desc_free(struct virt_dma_desc *vdesc)
> +{
> + kfree(container_of(vdesc, struct jz4740_dma_desc, vdesc));
> +}
> +
> +static int jz4740_dma_probe(struct platform_device *pdev)
> +{
> + struct jz4740_dmaengine_chan *chan;
> + struct jz4740_dma_dev *dmadev;
> + struct dma_device *dd;
> + unsigned int i;
> + int ret;
> +
> + dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL);
> + if (!dmadev)
> + return -EINVAL;
> +
> + dd = &dmadev->ddev;
> +
> + dma_cap_set(DMA_SLAVE, dd->cap_mask);
> + dma_cap_set(DMA_CYCLIC, dd->cap_mask);
> + dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources;
> + dd->device_free_chan_resources = jz4740_dma_free_chan_resources;
> + dd->device_tx_status = jz4740_dma_tx_status;
> + dd->device_issue_pending = jz4740_dma_issue_pending;
> + dd->device_prep_slave_sg = jz4740_dma_prep_slave_sg;
> + dd->device_prep_dma_cyclic = jz4740_dma_prep_dma_cyclic;
> + dd->device_control = jz4740_dma_control;
> + dd->dev = &pdev->dev;
> + dd->chancnt = 6;
hard coding is not advised
> + INIT_LIST_HEAD(&dd->channels);
> +
> + for (i = 0; i < dd->chancnt; i++) {
> + chan = &dmadev->chan[i];
> + chan->vchan.desc_free = jz4740_dma_desc_free;
> + vchan_init(&chan->vchan, dd);
> + }
> +
> + ret = dma_async_device_register(dd);
> + if (ret)
> + return ret;
> +
> + platform_set_drvdata(pdev, dmadev);
> +
> + return 0;
> +}
> +
> +static int jz4740_dma_remove(struct platform_device *pdev)
> +{
> + struct jz4740_dma_dev *dmadev = platform_get_drvdata(pdev);
> +
> + dma_async_device_unregister(&dmadev->ddev);
> +
> + return 0;
> +}
> +
> +static struct platform_driver jz4740_dma_driver = {
> + .probe = jz4740_dma_probe,
> + .remove = jz4740_dma_remove,
> + .driver = {
> + .name = "jz4740-dma",
> + .owner = THIS_MODULE,
> + },
> +};
> +module_platform_driver(jz4740_dma_driver);
typically lot of dma driver like to be higher up in the module order. The reason
is to have device initialized before clients, pls check if you need that
--
~Vinod
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-24 5:58 ` Lars-Peter Clausen
@ 2013-05-24 5:54 ` Vinod Koul
2013-05-24 6:41 ` Lars-Peter Clausen
0 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2013-05-24 5:54 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On Fri, May 24, 2013 at 07:58:04AM +0200, Lars-Peter Clausen wrote:
> This one needs both.
>
> >> + jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
> >> + jzcfg.request_type = config->slave_id;
> >> +
> >> + chan->config = *config;
> >> +
> >> + jz4740_dma_configure(chan->jz_chan, &jzcfg);
> >> +
> >> + return 0;
> > You are NOT use src_addr/dstn_addr? How else are you passing the periphral
> > address?
> I'm saving the whole config, which will later be used to retrieve the source or
> dest address.
well I missed that and it is a bad idea. You dont know when client has
freed/thrown the pointer so copy this instead..
>
> >> +}
> [...]
> >> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
> >> +{
> >> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> >> +
> >> + chan->jz_chan = jz4740_dma_request(chan, NULL);
> >> + if (!chan->jz_chan)
> >> + return -EBUSY;
> >> +
> >> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
> >> +
> >> + return 0;
> > Zero is not expected value, you need to return the descriptors allocated
> > sucessfully.
>
> Well, zero descriptors have been allocated. As far as I can see only a negative
> return value is treated as an error. Also the core doesn't seem to use the
> return value for anything else but checking if it is an error.
This is the API defination
* @device_alloc_chan_resources: allocate resources and return the
* number of allocated descriptors
> >> +}
> >> +
> [...]
> >> + dd->chancnt = 6;
> > hard coding is not advised
>
> But there are 6 channels ;)
JZ4740_MAX_CH 6 :)
--
~Vinod
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-24 4:59 ` Vinod Koul
@ 2013-05-24 5:58 ` Lars-Peter Clausen
2013-05-24 5:54 ` Vinod Koul
0 siblings, 1 reply; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-24 5:58 UTC (permalink / raw)
To: Vinod Koul
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On 05/24/2013 06:59 AM, Vinod Koul wrote:
> On Thu, May 23, 2013 at 10:36:24PM +0200, Lars-Peter Clausen wrote:
>> This patch adds dmaengine support for the JZ4740 DMA controller. For now the
>> driver will be a wrapper around the custom JZ4740 DMA API. Once all users of the
>> custom JZ4740 DMA API have been converted to the dmaengine API the custom API
>> will be removed and direct hardware access will be added to the dmaengine
>> driver.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> ---
>
>> +static enum jz4740_dma_width jz4740_dma_width(enum dma_slave_buswidth width)
>> +{
>> + switch (width) {
>> + case DMA_SLAVE_BUSWIDTH_1_BYTE:
>> + return JZ4740_DMA_WIDTH_8BIT;
>> + case DMA_SLAVE_BUSWIDTH_2_BYTES:
>> + return JZ4740_DMA_WIDTH_16BIT;
>> + case DMA_SLAVE_BUSWIDTH_4_BYTES:
>> + return JZ4740_DMA_WIDTH_32BIT;
>> + default:
>> + return JZ4740_DMA_WIDTH_32BIT;
>> + }
> Only diff between the values here and dmaengien values is JZ4740_DMA_WIDTH_32BIT
> as 0. But the header tells me taht its default and SIZE one has values in that
> pattern too. If that is the case you maybe able to get rid on conversion and use
> dmaengine values directly.
>
I'd prefer to keep it the way it is. The JZ4740_DMA_WIDTH constants end up
being written to the hardware, while the DMA_SLAVE_BUSWIDTH constants are Linux
internal. I prefer to not mix these two up.
>> +}
>> +
>> +static enum jz4740_dma_transfer_size jz4740_dma_maxburst(u32 maxburst)
>> +{
>> + if (maxburst <= 1)
>> + return JZ4740_DMA_TRANSFER_SIZE_1BYTE;
>> + else if (maxburst <= 3)
>> + return JZ4740_DMA_TRANSFER_SIZE_2BYTE;
>> + else if (maxburst <= 15)
>> + return JZ4740_DMA_TRANSFER_SIZE_4BYTE;
>> + else if (maxburst <= 31)
>> + return JZ4740_DMA_TRANSFER_SIZE_16BYTE;
>> +
>> + return JZ4740_DMA_TRANSFER_SIZE_32BYTE;
>> +}
>> +
>> +static int jz4740_dma_slave_config(struct dma_chan *c,
>> + const struct dma_slave_config *config)
>> +{
>> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
>> + struct jz4740_dma_config jzcfg;
>> +
>> + switch (config->direction) {
>> + case DMA_MEM_TO_DEV:
>> + jzcfg.flags = JZ4740_DMA_SRC_AUTOINC;
>> + jzcfg.transfer_size = jz4740_dma_maxburst(config->dst_maxburst);
>> + break;
>> + case DMA_DEV_TO_MEM:
>> + jzcfg.flags = JZ4740_DMA_DST_AUTOINC;
>> + jzcfg.transfer_size = jz4740_dma_maxburst(config->src_maxburst);
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> +
>> + jzcfg.src_width = jz4740_dma_width(config->src_addr_width);
>> + jzcfg.dst_width = jz4740_dma_width(config->dst_addr_width);
> this should be direction based, typically DMA engines have only one width to be
> programmed.
This one needs both.
>> + jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
>> + jzcfg.request_type = config->slave_id;
>> +
>> + chan->config = *config;
>> +
>> + jz4740_dma_configure(chan->jz_chan, &jzcfg);
>> +
>> + return 0;
> You are NOT use src_addr/dstn_addr? How else are you passing the periphral
> address?
I'm saving the whole config, which will later be used to retrieve the source or
dest address.
>> +}
[...]
>> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
>> +{
>> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
>> +
>> + chan->jz_chan = jz4740_dma_request(chan, NULL);
>> + if (!chan->jz_chan)
>> + return -EBUSY;
>> +
>> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
>> +
>> + return 0;
> Zero is not expected value, you need to return the descriptors allocated
> sucessfully.
Well, zero descriptors have been allocated. As far as I can see only a negative
return value is treated as an error. Also the core doesn't seem to use the
return value for anything else but checking if it is an error.
>> +}
>> +
[...]
>> + dd->chancnt = 6;
> hard coding is not advised
But there are 6 channels ;)
[...]
>> +
>> +static struct platform_driver jz4740_dma_driver = {
>> + .probe = jz4740_dma_probe,
>> + .remove = jz4740_dma_remove,
>> + .driver = {
>> + .name = "jz4740-dma",
>> + .owner = THIS_MODULE,
>> + },
>> +};
>> +module_platform_driver(jz4740_dma_driver);
> typically lot of dma driver like to be higher up in the module order. The reason
> is to have device initialized before clients, pls check if you need that
I don't need it.
Thanks for the quick review.
- Lars
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-24 5:54 ` Vinod Koul
@ 2013-05-24 6:41 ` Lars-Peter Clausen
2013-05-24 7:54 ` Vinod Koul
0 siblings, 1 reply; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-24 6:41 UTC (permalink / raw)
To: Vinod Koul
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On 05/24/2013 07:54 AM, Vinod Koul wrote:
> On Fri, May 24, 2013 at 07:58:04AM +0200, Lars-Peter Clausen wrote:
>> This one needs both.
>>
>>>> + jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
>>>> + jzcfg.request_type = config->slave_id;
>>>> +
>>>> + chan->config = *config;
>>>> +
>>>> + jz4740_dma_configure(chan->jz_chan, &jzcfg);
>>>> +
>>>> + return 0;
>>> You are NOT use src_addr/dstn_addr? How else are you passing the periphral
>>> address?
>> I'm saving the whole config, which will later be used to retrieve the source or
>> dest address.
> well I missed that and it is a bad idea. You dont know when client has
> freed/thrown the pointer so copy this instead..
I do copy the full config, not just the pointer to the config. Although
src_addr and dest_addr are the only two fields which are used later on at this
point. So I could change it to just copy src_addr and dest_addr, or well just
one of them depending on the direction.
>
>>
>>>> +}
>> [...]
>>>> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
>>>> +{
>>>> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
>>>> +
>>>> + chan->jz_chan = jz4740_dma_request(chan, NULL);
>>>> + if (!chan->jz_chan)
>>>> + return -EBUSY;
>>>> +
>>>> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
>>>> +
>>>> + return 0;
>>> Zero is not expected value, you need to return the descriptors allocated
>>> sucessfully.
>>
>> Well, zero descriptors have been allocated. As far as I can see only a negative
>> return value is treated as an error. Also the core doesn't seem to use the
>> return value for anything else but checking if it is an error.
> This is the API defination
> * @device_alloc_chan_resources: allocate resources and return the
> * number of allocated descriptors
>
But 0 is still the number of descriptors that have been pre-allocated.
- Lars
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-24 6:41 ` Lars-Peter Clausen
@ 2013-05-24 7:54 ` Vinod Koul
2013-05-24 8:39 ` [alsa-devel] " Lars-Peter Clausen
0 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2013-05-24 7:54 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On Fri, May 24, 2013 at 08:41:05AM +0200, Lars-Peter Clausen wrote:
> On 05/24/2013 07:54 AM, Vinod Koul wrote:
> > On Fri, May 24, 2013 at 07:58:04AM +0200, Lars-Peter Clausen wrote:
> >> This one needs both.
> >>
> >>>> + jzcfg.mode = JZ4740_DMA_MODE_SINGLE;
> >>>> + jzcfg.request_type = config->slave_id;
> >>>> +
> >>>> + chan->config = *config;
> >>>> +
> >>>> + jz4740_dma_configure(chan->jz_chan, &jzcfg);
> >>>> +
> >>>> + return 0;
> >>> You are NOT use src_addr/dstn_addr? How else are you passing the periphral
> >>> address?
> >> I'm saving the whole config, which will later be used to retrieve the source or
> >> dest address.
> > well I missed that and it is a bad idea. You dont know when client has
> > freed/thrown the pointer so copy this instead..
>
> I do copy the full config, not just the pointer to the config. Although
> src_addr and dest_addr are the only two fields which are used later on at this
> point. So I could change it to just copy src_addr and dest_addr, or well just
> one of them depending on the direction.
One of them based on direction would be right
>
> >
> >>
> >>>> +}
> >> [...]
> >>>> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
> >>>> +{
> >>>> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
> >>>> +
> >>>> + chan->jz_chan = jz4740_dma_request(chan, NULL);
> >>>> + if (!chan->jz_chan)
> >>>> + return -EBUSY;
> >>>> +
> >>>> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
> >>>> +
> >>>> + return 0;
> >>> Zero is not expected value, you need to return the descriptors allocated
> >>> sucessfully.
> >>
> >> Well, zero descriptors have been allocated. As far as I can see only a negative
> >> return value is treated as an error. Also the core doesn't seem to use the
> >> return value for anything else but checking if it is an error.
> > This is the API defination
> > * @device_alloc_chan_resources: allocate resources and return the
> > * number of allocated descriptors
> >
>
> But 0 is still the number of descriptors that have been pre-allocated.
and that should change, typically the driver will preallocate a pool of
descriptors. These are to be used later for .device_prep_xxx calls.
--
~Vinod
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [alsa-devel] [PATCH 3/6] dma: Add a jz4740 dmaengine driver
2013-05-24 7:54 ` Vinod Koul
@ 2013-05-24 8:39 ` Lars-Peter Clausen
0 siblings, 0 replies; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-24 8:39 UTC (permalink / raw)
To: Vinod Koul
Cc: linux-mips, alsa-devel, Liam Girdwood, Ralf Baechle, linux-kernel,
Mark Brown, Maarten ter Huurne
>>>>>> +static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
>>>>>> +{
>>>>>> + struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
>>>>>> +
>>>>>> + chan->jz_chan = jz4740_dma_request(chan, NULL);
>>>>>> + if (!chan->jz_chan)
>>>>>> + return -EBUSY;
>>>>>> +
>>>>>> + jz4740_dma_set_complete_cb(chan->jz_chan, jz4740_dma_complete_cb);
>>>>>> +
>>>>>> + return 0;
>>>>> Zero is not expected value, you need to return the descriptors allocated
>>>>> sucessfully.
>>>>
>>>> Well, zero descriptors have been allocated. As far as I can see only a negative
>>>> return value is treated as an error. Also the core doesn't seem to use the
>>>> return value for anything else but checking if it is an error.
>>> This is the API defination
>>> * @device_alloc_chan_resources: allocate resources and return the
>>> * number of allocated descriptors
>>>
>>
>> But 0 is still the number of descriptors that have been pre-allocated.
> and that should change, typically the driver will preallocate a pool of
> descriptors. These are to be used later for .device_prep_xxx calls.
>
Since the size of the descriptor is not know in advance this is not possible.
- Lars
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver
2013-05-23 20:36 ` [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver Lars-Peter Clausen
@ 2013-05-25 15:16 ` Mark Brown
0 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2013-05-25 15:16 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Ralf Baechle, Vinod Koul, Liam Girdwood, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
[-- Attachment #1: Type: text/plain, Size: 269 bytes --]
On Thu, May 23, 2013 at 10:36:26PM +0200, Lars-Peter Clausen wrote:
> Since there is a dmaengine driver for the jz4740 DMA controller now we can use
> the generic dmaengine PCM driver instead of a custom one.
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/6] Convert JZ4740 to dmaengine
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
` (5 preceding siblings ...)
2013-05-23 20:36 ` [PATCH 6/6] MIPS: jz4740: Remove custom DMA API Lars-Peter Clausen
@ 2013-05-29 9:31 ` Ralf Baechle
6 siblings, 0 replies; 17+ messages in thread
From: Ralf Baechle @ 2013-05-29 9:31 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Vinod Koul, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On Thu, May 23, 2013 at 10:36:21PM +0200, Lars-Peter Clausen wrote:
> done in 3 steps:
> 1) Add a dmaengine driver which wraps the custom JZ4740 DMA API
> 2) Update all users of the JZ4740 DMA API to use dmaengine instead
> 3) Remove the custom API and move all direct hardware access to the
> dmaengine driver.
>
> The first two patches in the series also make sure that the clock of the DMA
> core is enabled.
>
> Since the patches in this series depend on each other I'd prefer if they could
> all go through the DMA tree.
No problem - though my experience is that code for MIPS systems, including
drivers receives most testing if it lives in the MIPS git tree, less in
linux-next and barely any in in other subsystem-specific trees.
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Ralf
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 0/6] Convert JZ4740 to dmaengine
@ 2013-05-30 16:24 Lars-Peter Clausen
2013-06-21 14:13 ` Vinod Koul
0 siblings, 1 reply; 17+ messages in thread
From: Lars-Peter Clausen @ 2013-05-30 16:24 UTC (permalink / raw)
To: Ralf Baechle, Vinod Koul, Liam Girdwood, Mark Brown
Cc: Maarten ter Huurne, linux-mips, linux-kernel, alsa-devel,
Lars-Peter Clausen
Hi,
This series replaces the custom JZ4740 DMA API with a dmaengine driver. This is
done in 3 steps:
1) Add a dmaengine driver which wraps the custom JZ4740 DMA API
2) Update all users of the JZ4740 DMA API to use dmaengine instead
3) Remove the custom API and move all direct hardware access to the
dmaengine driver.
The first two patches in the series also make sure that the clock of the DMA
core is enabled.
Since the patches in this series depend on each other I'd prefer if they could
all go through the DMA tree.
There are a few minor changes to the patch 3 in v2 of this series, all other
patches are identical to v1.
- Lars
Lars-Peter Clausen (4):
dma: Add a jz4740 dmaengine driver
MIPS: jz4740: Register jz4740 DMA device
ASoC: jz4740: Use the generic dmaengine PCM driver
MIPS: jz4740: Remove custom DMA API
Maarten ter Huurne (2):
MIPS: jz4740: Correct clock gate bit for DMA controller
MIPS: jz4740: Acquire and enable DMA controller clock
arch/mips/include/asm/mach-jz4740/dma.h | 56 ---
arch/mips/include/asm/mach-jz4740/platform.h | 1 +
arch/mips/jz4740/Makefile | 2 +-
arch/mips/jz4740/board-qi_lb60.c | 1 +
arch/mips/jz4740/clock.c | 2 +-
arch/mips/jz4740/dma.c | 287 -------------
arch/mips/jz4740/platform.c | 21 +
drivers/dma/Kconfig | 6 +
drivers/dma/Makefile | 1 +
drivers/dma/dma-jz4740.c | 617 +++++++++++++++++++++++++++
sound/soc/jz4740/Kconfig | 1 +
sound/soc/jz4740/jz4740-i2s.c | 48 +--
sound/soc/jz4740/jz4740-pcm.c | 310 +-------------
sound/soc/jz4740/jz4740-pcm.h | 20 -
14 files changed, 676 insertions(+), 697 deletions(-)
delete mode 100644 arch/mips/jz4740/dma.c
create mode 100644 drivers/dma/dma-jz4740.c
delete mode 100644 sound/soc/jz4740/jz4740-pcm.h
--
1.8.2.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/6] Convert JZ4740 to dmaengine
2013-05-30 16:24 Lars-Peter Clausen
@ 2013-06-21 14:13 ` Vinod Koul
0 siblings, 0 replies; 17+ messages in thread
From: Vinod Koul @ 2013-06-21 14:13 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: Ralf Baechle, Liam Girdwood, Mark Brown, Maarten ter Huurne,
linux-mips, linux-kernel, alsa-devel
On Thu, May 30, 2013 at 06:24:59PM +0200, Lars-Peter Clausen wrote:
> Hi,
>
> This series replaces the custom JZ4740 DMA API with a dmaengine driver. This is
> done in 3 steps:
> 1) Add a dmaengine driver which wraps the custom JZ4740 DMA API
> 2) Update all users of the JZ4740 DMA API to use dmaengine instead
> 3) Remove the custom API and move all direct hardware access to the
> dmaengine driver.
>
> The first two patches in the series also make sure that the clock of the DMA
> core is enabled.
>
> Since the patches in this series depend on each other I'd prefer if they could
> all go through the DMA tree.
>
> There are a few minor changes to the patch 3 in v2 of this series, all other
> patches are identical to v1.
Applied all expect the "ASoC: jz4740: Use the generic dmaengine PCM driver". Can
you rebase that on slave dma-next and resend
Fixed up struct alignment manually in 4th one
--
~Vinod
>
> - Lars
>
> Lars-Peter Clausen (4):
> dma: Add a jz4740 dmaengine driver
> MIPS: jz4740: Register jz4740 DMA device
> ASoC: jz4740: Use the generic dmaengine PCM driver
> MIPS: jz4740: Remove custom DMA API
>
> Maarten ter Huurne (2):
> MIPS: jz4740: Correct clock gate bit for DMA controller
> MIPS: jz4740: Acquire and enable DMA controller clock
>
> arch/mips/include/asm/mach-jz4740/dma.h | 56 ---
> arch/mips/include/asm/mach-jz4740/platform.h | 1 +
> arch/mips/jz4740/Makefile | 2 +-
> arch/mips/jz4740/board-qi_lb60.c | 1 +
> arch/mips/jz4740/clock.c | 2 +-
> arch/mips/jz4740/dma.c | 287 -------------
> arch/mips/jz4740/platform.c | 21 +
> drivers/dma/Kconfig | 6 +
> drivers/dma/Makefile | 1 +
> drivers/dma/dma-jz4740.c | 617 +++++++++++++++++++++++++++
> sound/soc/jz4740/Kconfig | 1 +
> sound/soc/jz4740/jz4740-i2s.c | 48 +--
> sound/soc/jz4740/jz4740-pcm.c | 310 +-------------
> sound/soc/jz4740/jz4740-pcm.h | 20 -
> 14 files changed, 676 insertions(+), 697 deletions(-)
> delete mode 100644 arch/mips/jz4740/dma.c
> create mode 100644 drivers/dma/dma-jz4740.c
> delete mode 100644 sound/soc/jz4740/jz4740-pcm.h
>
> --
> 1.8.2.1
>
--
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2013-06-21 14:53 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-23 20:36 [PATCH 0/6] Convert JZ4740 to dmaengine Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 1/6] MIPS: jz4740: Correct clock gate bit for DMA controller Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 2/6] MIPS: jz4740: Acquire and enable DMA controller clock Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 3/6] dma: Add a jz4740 dmaengine driver Lars-Peter Clausen
2013-05-24 4:59 ` Vinod Koul
2013-05-24 5:58 ` Lars-Peter Clausen
2013-05-24 5:54 ` Vinod Koul
2013-05-24 6:41 ` Lars-Peter Clausen
2013-05-24 7:54 ` Vinod Koul
2013-05-24 8:39 ` [alsa-devel] " Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 4/6] MIPS: jz4740: Register jz4740 DMA device Lars-Peter Clausen
2013-05-23 20:36 ` [PATCH 5/6] ASoC: jz4740: Use the generic dmaengine PCM driver Lars-Peter Clausen
2013-05-25 15:16 ` Mark Brown
2013-05-23 20:36 ` [PATCH 6/6] MIPS: jz4740: Remove custom DMA API Lars-Peter Clausen
2013-05-29 9:31 ` [PATCH 0/6] Convert JZ4740 to dmaengine Ralf Baechle
-- strict thread matches above, loose matches on Subject: below --
2013-05-30 16:24 Lars-Peter Clausen
2013-06-21 14:13 ` Vinod Koul
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox