[PATCH] dmaengine: pl330: Set residue in tx_status callback
Padma Venkat
padma.kvr at gmail.com
Mon Dec 1 21:38:15 PST 2014
Hi Vinod/Lars,
On 11/26/14, Padmavathi Venna <padma.v at samsung.com> wrote:
> Fill txstate.residue with the amount of bytes remaining in the current
> transfer if the transfer is not complete. This will be of particular
> use to i2s DMA transfers, providing more accurate hw_ptr values to ASoC.
>
> I had taken the code from Dylan Reid <dgreid at chromium.org> patch from the
> below link and modified according to the current dmaengine framework.
> http://comments.gmane.org/gmane.linux.kernel.samsung-soc/23007
>
> Cc: Dylan Reid <dgreid at chromium.org>
> Signed-off-by: Padmavathi Venna <padma.v at samsung.com>
> ---
>
> This patch has been tested for audio playback on exynos5420 peach-pit.
>
> drivers/dma/pl330.c | 67
> +++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index b7493d2..db880ae 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -2182,11 +2182,74 @@ static void pl330_free_chan_resources(struct
> dma_chan *chan)
> pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
> }
>
> +static inline int
> +pl330_src_addr_in_desc(struct dma_pl330_desc *desc, unsigned int sar)
> +{
> + return ((desc->px.src_addr <= sar) &&
> + (sar <= (desc->px.src_addr + desc->px.bytes)));
> +}
> +
> +static inline int
> +pl330_dst_addr_in_desc(struct dma_pl330_desc *desc, unsigned int dar)
> +{
> + return ((desc->px.dst_addr <= dar) &&
> + (dar <= (desc->px.dst_addr + desc->px.bytes)));
> +}
> +
> static enum dma_status
> pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
> struct dma_tx_state *txstate)
> {
> - return dma_cookie_status(chan, cookie, txstate);
> + dma_addr_t sar, dar;
> + struct dma_pl330_chan *pch = to_pchan(chan);
> + void __iomem *regs = pch->dmac->base;
> + struct pl330_thread *thrd = pch->thread;
> + struct dma_pl330_desc *desc;
> + unsigned int residue = 0;
> + unsigned long flags;
> + bool first = true;
> + dma_cookie_t first_c, current_c;
> + dma_cookie_t used;
> + enum dma_status ret;
> +
> + ret = dma_cookie_status(chan, cookie, txstate);
> + if (ret == DMA_COMPLETE || !txstate)
> + return ret;
> +
> + used = txstate->used;
> +
> + spin_lock_irqsave(&pch->lock, flags);
> + sar = readl(regs + SA(thrd->id));
> + dar = readl(regs + DA(thrd->id));
> +
> + list_for_each_entry(desc, &pch->work_list, node) {
> + if (desc->status == BUSY) {
> + current_c = desc->txd.cookie;
> + if (first) {
> + first_c = desc->txd.cookie;
> + first = false;
> + }
> +
> + if (first_c < current_c)
> + residue += desc->px.bytes;
> + else {
> + if (desc->rqcfg.src_inc && pl330_src_addr_in_desc(desc, sar)) {
> + residue += desc->px.bytes;
> + residue -= sar - desc->px.src_addr;
> + } else if (desc->rqcfg.dst_inc && pl330_dst_addr_in_desc(desc, dar)) {
> + residue += desc->px.bytes;
> + residue -= dar - desc->px.dst_addr;
> + }
> + }
> + } else if (desc->status == PREP)
> + residue += desc->px.bytes;
> +
> + if (desc->txd.cookie == used)
> + break;
> + }
> + spin_unlock_irqrestore(&pch->lock, flags);
> + dma_set_residue(txstate, residue);
> + return ret;
> }
>
> static void pl330_issue_pending(struct dma_chan *chan)
> @@ -2631,7 +2694,7 @@ static int pl330_dma_device_slave_caps(struct dma_chan
> *dchan,
> caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> caps->cmd_pause = false;
> caps->cmd_terminate = true;
> - caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
> + caps->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
>
> return 0;
> }
Any comment on this patch?
Thanks
Padma
> --
> 1.7.4.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc"
> in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
More information about the linux-arm-kernel
mailing list