MLK-11344-7: dma: imx-sdma: Add hdmi audio support in sdma
authorShengjiu Wang <shengjiu.wang@freescale.com>
Fri, 5 Sep 2014 10:51:36 +0000 (18:51 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:47:24 +0000 (14:47 -0500)
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 <shengjiu.wang@freescale.com>
Signed-off-by: Robin Gong <b38343@freescale.com>
(cherry picked from commit dafddac916a03ae4477e2de7c1b7ad291f956f68)

Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
drivers/dma/imx-sdma.c
include/linux/platform_data/dma-imx.h

index 3c9a57a..ccc6c08 100644 (file)
@@ -50,6 +50,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.
 
index 901222c..f3b089e 100644 (file)
@@ -777,7 +777,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);
                else
                        tasklet_schedule(&sdmac->tasklet);
@@ -873,6 +874,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;
        }
@@ -917,11 +921,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;
@@ -1301,9 +1310,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);
 
@@ -1323,6 +1332,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);
@@ -1397,6 +1411,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 *
index 63fe0a0..092133a 100644 (file)
@@ -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 {