This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ALSA - DMA ping-pong

Guru 20755 points


Hello,

I have configured dma with alsa and alsa works well with arecord and aplay.

But I'm not sure about the DMA: Does alsa always use dma, or does it depends on how we use the alsa libraries APIs ?

Thanks,

Ran

  • Ran,

    I think DMA usage depends on which ALSA function is used. DMA is involved only when there is data transfer started (playback or record).

    BR
    Pavel
  • Hi Pavel,

    It seems according to code that DMA is always used whenever there is data transfer (without care for the specific alsa function for the data transfer).

    davinci_pcm.c:

    davinci_pcm_open() -> davinci_pcm_dma_request(substream) -> link = prtd->asp_channel = edma_alloc_channel(params->channel)

    I also see that without configuring dma correct in kernel then davinci_pcm_open will return error.

     

    Best Regards,

    Ran

  • Hi Pavel,

    I am mainly interetsed in working with dma in ping-pong mode.

    I see in davinci_pcm.c a comment "not used with ping/pong" :

    /*

      * Not used with ping/pong

      */

     static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)

     {

    .....

             period_size = snd_pcm_lib_period_bytes(substream);

             dma_offset = prtd->period * period_size;

             dma_pos = runtime->dma_addr + dma_offset;

    ....


    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    src = dma_pos;
    dst = prtd->params->dma_addr;
    src_bidx = data_type;
    dst_bidx = 0;
    src_cidx = data_type * fifo_level;
    dst_cidx = 0;
    } else {
    ....

    acnt = prtd->params->acnt;
    edma_set_src(link, src, INCR, W8BIT);
    edma_set_dest(link, dst, INCR, W8BIT);

    }

    But this comment is not well understood becuase you can see that dma with offset/length according to alsa period parameter.

    So what is the meaning of the comment "not used with ping/pong" ?

    Regards,

    Ran

  • Ran,

    Ran Shalit said:

    It seems according to code that DMA is always used whenever there is data transfer (without care for the specific alsa function for the data transfer).

    davinci_pcm.c:

    davinci_pcm_open() -> davinci_pcm_dma_request(substream) -> link = prtd->asp_channel = edma_alloc_channel(params->channel)

    Which ALSA API function invokes davinci_pcm_open() ?

    BR
    Pavel

  • Hi Pavel,

    Is see that /sound/core/pcm* files use substream->open() for pcm.
    The thing we are main concrened with now, is to support ping/pong with DMA.
    From what I read about dma&alsa (there is no much info about dma & alsa), I think that the period parameter should be used for the ping-pong.
    and it also seems reasonable in davinci code, becuase the dma offset is determined according to period:

    dma_offset = prtd->period * period_size;
    dma_pos = runtime->dma_addr + dma_offset;

    Is there any reason for the commened "Not used with ping/pong" in the header of:

    static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)

    Do you think that ping-pong is already supported ?

    Regards,
    Ran
  • In addition, to this I will add that
    arecord utility will also invoke this pcm open :
    arecord -> snd_pcm_open -> davinci_pcm_open

    Regards,
    Ran
  • Ran,

    Linking can be performed in order to reload the same transfer or a completely different transfer. Often systems employ a ping-pong buffering system. In this case, when the ping transfer is done, the EDMA can auto reload the pong transfer and on and on it goes.

    See also the below e2e thread:
    e2e.ti.com/.../252002

    Check also DM814x TRM, chapter EDMA
  • Hi Pavel,

    Thank you very much for the hints.
    But Isn't using period with dma_pos inside dma buffer is already a ping-pong method (which is already embedded in davinci code) ?
    dma_offset = prtd->period * period_size;
    dma_pos = runtime->dma_addr + dma_offset;

    Regards,
    Ran
  • Ran Shalit said:
    But Isn't using period with dma_pos inside dma buffer is already a ping-pong method (which is already embedded in davinci code) ?

    I don't think so.

    Ping-pong buffering is a simple technique that allows the CPU activity to be distanced from the EDMA activity. This means that there are multiple (usually two) sets of data buffers for all incoming and outgoing data streams. While the EDMA transfers the data into and out of the ping buffers, the CPU manipulates the data in the pong buffers. When both CPU and EDMA activity completes, they switch. The EDMA then writes over the old input data and transfers the new output data.

    To change the continuous operation example, such that a ping-pong buffering scheme is used, the EDMA channels need only a moderate change. Instead of one parameter set, there are two; one for transferring data to/from the ping buffers and one for transferring data to/from the pong buffers. As soon as one transfer completes, the channel loads the PaRAM set for the other and the data transfers continue.


    davinci_pcm_enqueue_dma() use only asp_link[0]. While for ping-pong, asp_link[0] and asp_link[1] should be used, see:

    ping_pong_dma_setup()

    request_ping_pong()


    BR
    Pavel