From f10eac3ca6c0cc01ed628b93237ec403865a6233 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 5 Sep 2014 18:51:36 +0800 Subject: MLK-11344-7: dma: imx-sdma: Add hdmi audio support in sdma cherry-pick below patch from v3.14.y: ENGR00329948-3: dma: imx-sdma: Add hdmi audio support in sdma There's a missing script for hdmi audio support in current sdma driver, thus add it. This HDMI script doesn't use bd to copy memory like a normal one does but only to update the memory address for HDMI internal AHB DMA and then trigger its procedure automatically. Signed-off-by: Shengjiu Wang Signed-off-by: Robin Gong (cherry picked from commit dafddac916a03ae4477e2de7c1b7ad291f956f68) --- .../devicetree/bindings/dma/fsl-imx-sdma.txt | 1 + drivers/dma/imx-sdma.c | 32 +++++++++++++++++----- include/linux/platform_data/dma-imx.h | 3 +- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index 901ed92f767d..d29c17a91729 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt @@ -55,6 +55,7 @@ The full ID of peripheral types can be found below. 22 SSI Dual FIFO (needs firmware ver >= 2) 23 Shared ASRC 24 SAI + 25 HDMI Audio The third cell specifies the transfer priority as below. diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a67cdcdcb5f7..df8b1ed2f863 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -749,7 +749,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) int channel = fls(stat) - 1; struct sdma_channel *sdmac = &sdma->channel[channel]; - if (sdmac->flags & IMX_DMA_SG_LOOP) + if ((sdmac->flags & IMX_DMA_SG_LOOP) && + (sdmac->peripheral_type != IMX_DMATYPE_HDMI)) sdma_update_channel_loop(sdmac); tasklet_schedule(&sdmac->tasklet); @@ -846,6 +847,9 @@ static void sdma_get_pc(struct sdma_channel *sdmac, case IMX_DMATYPE_IPU_MEMORY: emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr; break; + case IMX_DMATYPE_HDMI: + emi_2_per = sdma->script_addrs->hdmi_dma_addr; + break; default: break; } @@ -890,11 +894,16 @@ static int sdma_load_context(struct sdma_channel *sdmac) /* Send by context the event mask,base address for peripheral * and watermark level */ - context->gReg[0] = sdmac->event_mask[1]; - context->gReg[1] = sdmac->event_mask[0]; - context->gReg[2] = sdmac->per_addr; - context->gReg[6] = sdmac->shp_addr; - context->gReg[7] = sdmac->watermark_level; + if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) { + context->gReg[4] = sdmac->per_addr; + context->gReg[6] = sdmac->shp_addr; + } else { + context->gReg[0] = sdmac->event_mask[1]; + context->gReg[1] = sdmac->event_mask[0]; + context->gReg[2] = sdmac->per_addr; + context->gReg[6] = sdmac->shp_addr; + context->gReg[7] = sdmac->watermark_level; + } bd0->mode.command = C0_SETDM; bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; @@ -1264,9 +1273,9 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( { struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; - int num_periods = buf_len / period_len; int channel = sdmac->channel; int ret, i = 0, buf = 0; + int num_periods; dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); @@ -1284,6 +1293,11 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( if (ret) goto err_out; + if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) + return &sdmac->desc; + else + num_periods = buf_len / period_len; + if (num_periods > NUM_BD) { dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n", channel, num_periods, NUM_BD); @@ -1358,6 +1372,10 @@ static int sdma_config(struct dma_chan *chan, sdmac->watermark_level |= (dmaengine_cfg->dst_maxburst << 16) & SDMA_WATERMARK_LEVEL_HWML; sdmac->word_size = dmaengine_cfg->dst_addr_width; + } else if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) { + sdmac->per_address = dmaengine_cfg->src_addr; + sdmac->per_address2 = dmaengine_cfg->dst_addr; + sdmac->watermark_level = 0; } else { sdmac->per_address = dmaengine_cfg->dst_addr; sdmac->watermark_level = dmaengine_cfg->dst_maxburst * diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index 63fe0a0584d5..092133a3036d 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2015 Freescale Semiconductor, Inc. All Rights Reserved. * * 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 @@ -42,6 +42,7 @@ enum sdma_peripheral_type { IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */ IMX_DMATYPE_ASRC_SP, /* Shared ASRC */ IMX_DMATYPE_SAI, /* SAI */ + IMX_DMATYPE_HDMI, /* HDMI Audio */ }; enum imx_dma_prio { -- cgit v1.2.3