DMA Drivers

For documentation of support devices, refer to Supported Devices.

Intro

Access to the DMA Controllers (DMAC) available on the platform is provided by the dma_get() function implemented by the library code. Reference to a DMAC instance obtained from dma_get() is represented by a pointer to struct dma. Each struct dma instance provides the dma_ops API used by the DMA clients to set up and run the DMA transmission.

class lib {

   dma_get(dmac_id) : struct dma*

   dma_put(struct dma*)

}

hide lib attributes



class dma_ops {

   channel_get()

   channel_put()

   start()

   stop()

   pause()

   release()

   status()

   set_config()

   set_cb()

   pm_context_restore()

   probe()

   remove()

}

hide dma_ops attributes



class dma_plat_data {

   id : uint32_t

   base : uint32_t

   channels : uint32_t

   irq : uint32_t

   drv_plat_data : void *

}

hide dma_plat_data methods



class "struct dma" as s_dma {

   plat_data : dma_plat_data

   lock : spinlock_t

   ops : const dma_ops *

   private : void *

}

hide s_dma methods



dma_ops - s_dma

s_dma -- dma_plat_data

s_dma <- lib : provides

Figure 50 DMA Driver API

Programming Flows

DMAC Initialization

In a one-time initialization phase, the ADSP goes to the D0 device power state. In this fully functional state, the platform registers its DMA drivers in the list maintained by the lib at startup.

Note

A static array of dma instances declared in the platform’s code may be replaced with a dynamic discovery of the DMA resources available on the platform, using capability registers if provided by the HW.

Any component from the audio package may use a DMA engine by obtaining a reference to the dma_ops interface from the lib’s list. This flow may happen an unlimited number of times during ADSP D0.

Channel Initialization & Data Transfer

participant client

participant lib

participant dma



== Obtaining Reference to DMAC ==

client -> lib : dma_get(capabilities)

client <-- lib : dma



== Start ==

client -> dma : dma_channel_get( stream tag )

client <-- dma : ch#



client -> dma : dma_set_cb( ch#, client.cb() )

client -> dma : dma_set_config( ch#, config )

client -> dma : dma_start( ch# )



== Transmission ==

...



== Stop ==

client -> dma : dma_stop( ch# )

client -> dma : dma_channel_put( ch# )

Figure 51 Channel Initialization & Data Transfer

In case the host co-manages the DMA HW and the channel is “allocated” by the host side, the FW component must wait until its params() API is called in order to learn the channel ID and pass it to the channel_get() request.

Using DMA Driver API

See DMA Drivers API

Note

The API is accessed through a common structure; however, an implementation may keep some specific private data, attached to the dma.private pointer.