alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* Verification of settings
@ 2016-07-11 19:10 Rob Nertney
  2016-07-11 19:29 ` Lars-Peter Clausen
  0 siblings, 1 reply; 4+ messages in thread
From: Rob Nertney @ 2016-07-11 19:10 UTC (permalink / raw)
  To: alsa-user, alsa-devel

Hi all,

Could I please get a sanity check on my hw_params?

I have a DMA which is providing between 1-16 channels of 4 bytes/ch worth
of data as a frame. I get an interrupt to my driver every frame's worth of
data (64 Bytes). The data is S32_LE, 16000Hz.

My DMA has 2 buffers, PING and PONG. Each receives an IRQ on a frame
length, and these local buffers are the size of a frame length (64Bytes).

#define MAX_BUFFER (64 * 2)
static struct snd_pcm_hardware my_pcm_hw =
{
  .info = (SNDRV_PCM_INFO_MMAP |
      SNDRV_PCM_INFO_INTERLEAVED |
      SNDRV_PCM_INFO_BLOCK_TRANSFER |
      SNDRV_PCM_INFO_MMAP_VALID),
  .formats          = SNDRV_PCM_FMTBIT_S32,
  .rates            = SNDRV_PCM_RATE_16000,
  .rate_min         = 16000,
  .rate_max         = 16000,
  .channels_min     = 1,
  .channels_max     = NUM_CHANNELS,
  .buffer_bytes_max = MAX_BUFFER,
  .period_bytes_min = 4,
  .period_bytes_max = 64,
  .periods_min      = 2,
  .periods_max      = 2,
};


My understanding is that the MAX_BUFFER needs to be at least twice the size
of a period so I don't underrun. .periods_max means the maximum number of
periods in a the alsa dma_area buffer, right?

So when my DMA fires its ISR, I copy from its local PING buffer to the
dma_area at offset 0, increment the buf_pos by the frame_length (64Bytes),
and call snd_pcm_period_elapsed.

My DMA fires its ISR for its local PONG buffer, copies to the
dma_area+buf_pos, increments buf_pos (now back to 0, since buffer only
holds 2 frames/periods), and I call snd_pcm_period_elapsed again, correct?

Thanks,
Rob

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Verification of settings
  2016-07-11 19:10 Verification of settings Rob Nertney
@ 2016-07-11 19:29 ` Lars-Peter Clausen
  2016-07-11 19:33   ` Rob Nertney
  0 siblings, 1 reply; 4+ messages in thread
From: Lars-Peter Clausen @ 2016-07-11 19:29 UTC (permalink / raw)
  To: Rob Nertney, alsa-user, alsa-devel

On 07/11/2016 09:10 PM, Rob Nertney wrote:
> Hi all,
> 
> Could I please get a sanity check on my hw_params?
> 
> I have a DMA which is providing between 1-16 channels of 4 bytes/ch worth
> of data as a frame. I get an interrupt to my driver every frame's worth of
> data (64 Bytes). The data is S32_LE, 16000Hz.
> 
> My DMA has 2 buffers, PING and PONG. Each receives an IRQ on a frame
> length, and these local buffers are the size of a frame length (64Bytes).
> 
> #define MAX_BUFFER (64 * 2)
> static struct snd_pcm_hardware my_pcm_hw =
> {
>   .info = (SNDRV_PCM_INFO_MMAP |
>       SNDRV_PCM_INFO_INTERLEAVED |
>       SNDRV_PCM_INFO_BLOCK_TRANSFER |
>       SNDRV_PCM_INFO_MMAP_VALID),
>   .formats          = SNDRV_PCM_FMTBIT_S32,
>   .rates            = SNDRV_PCM_RATE_16000,
>   .rate_min         = 16000,
>   .rate_max         = 16000,
>   .channels_min     = 1,
>   .channels_max     = NUM_CHANNELS,
>   .buffer_bytes_max = MAX_BUFFER,
>   .period_bytes_min = 4,
>   .period_bytes_max = 64,
>   .periods_min      = 2,
>   .periods_max      = 2,
> };
> 
> 
> My understanding is that the MAX_BUFFER needs to be at least twice the size
> of a period so I don't underrun. .periods_max means the maximum number of
> periods in a the alsa dma_area buffer, right?
> 
> So when my DMA fires its ISR, I copy from its local PING buffer to the
> dma_area at offset 0, increment the buf_pos by the frame_length (64Bytes),
> and call snd_pcm_period_elapsed.
> 
> My DMA fires its ISR for its local PONG buffer, copies to the
> dma_area+buf_pos, increments buf_pos (now back to 0, since buffer only
> holds 2 frames/periods), and I call snd_pcm_period_elapsed again, correct?

Hi,

In principle sounds OK. But there is not much of a point to use a
ping-pong buffer if you give the real buffer the same restrictions. You
might as well use the dma_area buffer as the target of the DMA in that
case. But since in your case the DMA is very restrictive in what it can
support it makes more sense to use the ping-pong buffer and broaden the
restrictions on the real buffer. Allow larger period sizes (only call
snd_pcm_period_elapsed() every N interrupts), allow more than two
periods and so on.

- Lars

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Verification of settings
  2016-07-11 19:29 ` Lars-Peter Clausen
@ 2016-07-11 19:33   ` Rob Nertney
  2016-07-12  2:00     ` Rob Nertney
  0 siblings, 1 reply; 4+ messages in thread
From: Rob Nertney @ 2016-07-11 19:33 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: alsa-user, alsa-devel

Thanks Lars.

My problem with the DMA is that it doesn't support cyclic mode, but does
support SG mode. I have to create a new descriptor every time, and
requeue/resubmit it. I don't want to drop any frames, so PONG is being
received while PING is being copied and resubmitted to the Linux queue.

On Mon, Jul 11, 2016 at 12:29 PM, Lars-Peter Clausen <lars@metafoo.de>
wrote:

> On 07/11/2016 09:10 PM, Rob Nertney wrote:
> > Hi all,
> >
> > Could I please get a sanity check on my hw_params?
> >
> > I have a DMA which is providing between 1-16 channels of 4 bytes/ch worth
> > of data as a frame. I get an interrupt to my driver every frame's worth
> of
> > data (64 Bytes). The data is S32_LE, 16000Hz.
> >
> > My DMA has 2 buffers, PING and PONG. Each receives an IRQ on a frame
> > length, and these local buffers are the size of a frame length (64Bytes).
> >
> > #define MAX_BUFFER (64 * 2)
> > static struct snd_pcm_hardware my_pcm_hw =
> > {
> >   .info = (SNDRV_PCM_INFO_MMAP |
> >       SNDRV_PCM_INFO_INTERLEAVED |
> >       SNDRV_PCM_INFO_BLOCK_TRANSFER |
> >       SNDRV_PCM_INFO_MMAP_VALID),
> >   .formats          = SNDRV_PCM_FMTBIT_S32,
> >   .rates            = SNDRV_PCM_RATE_16000,
> >   .rate_min         = 16000,
> >   .rate_max         = 16000,
> >   .channels_min     = 1,
> >   .channels_max     = NUM_CHANNELS,
> >   .buffer_bytes_max = MAX_BUFFER,
> >   .period_bytes_min = 4,
> >   .period_bytes_max = 64,
> >   .periods_min      = 2,
> >   .periods_max      = 2,
> > };
> >
> >
> > My understanding is that the MAX_BUFFER needs to be at least twice the
> size
> > of a period so I don't underrun. .periods_max means the maximum number of
> > periods in a the alsa dma_area buffer, right?
> >
> > So when my DMA fires its ISR, I copy from its local PING buffer to the
> > dma_area at offset 0, increment the buf_pos by the frame_length
> (64Bytes),
> > and call snd_pcm_period_elapsed.
> >
> > My DMA fires its ISR for its local PONG buffer, copies to the
> > dma_area+buf_pos, increments buf_pos (now back to 0, since buffer only
> > holds 2 frames/periods), and I call snd_pcm_period_elapsed again,
> correct?
>
> Hi,
>
> In principle sounds OK. But there is not much of a point to use a
> ping-pong buffer if you give the real buffer the same restrictions. You
> might as well use the dma_area buffer as the target of the DMA in that
> case. But since in your case the DMA is very restrictive in what it can
> support it makes more sense to use the ping-pong buffer and broaden the
> restrictions on the real buffer. Allow larger period sizes (only call
> snd_pcm_period_elapsed() every N interrupts), allow more than two
> periods and so on.
>
> - Lars
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Verification of settings
  2016-07-11 19:33   ` Rob Nertney
@ 2016-07-12  2:00     ` Rob Nertney
  0 siblings, 0 replies; 4+ messages in thread
From: Rob Nertney @ 2016-07-12  2:00 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: alsa-user, alsa-devel

Related question:

Once I have copied my data from PING into dma_area, and called
snd_pcm_period_elapsed, can I assume arecord has consumed that data by the
time i finish writing PONG, calling snd_pcm_period_elapsed, and hit the IRQ
to recopy PING?

in other words, what/where is the guarantee that arecord has consumed the
data in dma_area, such that the user can rewrite to it?



On Mon, Jul 11, 2016 at 12:33 PM, Rob Nertney <rob@rob-otics.com> wrote:

> Thanks Lars.
>
> My problem with the DMA is that it doesn't support cyclic mode, but does
> support SG mode. I have to create a new descriptor every time, and
> requeue/resubmit it. I don't want to drop any frames, so PONG is being
> received while PING is being copied and resubmitted to the Linux queue.
>
> On Mon, Jul 11, 2016 at 12:29 PM, Lars-Peter Clausen <lars@metafoo.de>
> wrote:
>
>> On 07/11/2016 09:10 PM, Rob Nertney wrote:
>> > Hi all,
>> >
>> > Could I please get a sanity check on my hw_params?
>> >
>> > I have a DMA which is providing between 1-16 channels of 4 bytes/ch
>> worth
>> > of data as a frame. I get an interrupt to my driver every frame's worth
>> of
>> > data (64 Bytes). The data is S32_LE, 16000Hz.
>> >
>> > My DMA has 2 buffers, PING and PONG. Each receives an IRQ on a frame
>> > length, and these local buffers are the size of a frame length
>> (64Bytes).
>> >
>> > #define MAX_BUFFER (64 * 2)
>> > static struct snd_pcm_hardware my_pcm_hw =
>> > {
>> >   .info = (SNDRV_PCM_INFO_MMAP |
>> >       SNDRV_PCM_INFO_INTERLEAVED |
>> >       SNDRV_PCM_INFO_BLOCK_TRANSFER |
>> >       SNDRV_PCM_INFO_MMAP_VALID),
>> >   .formats          = SNDRV_PCM_FMTBIT_S32,
>> >   .rates            = SNDRV_PCM_RATE_16000,
>> >   .rate_min         = 16000,
>> >   .rate_max         = 16000,
>> >   .channels_min     = 1,
>> >   .channels_max     = NUM_CHANNELS,
>> >   .buffer_bytes_max = MAX_BUFFER,
>> >   .period_bytes_min = 4,
>> >   .period_bytes_max = 64,
>> >   .periods_min      = 2,
>> >   .periods_max      = 2,
>> > };
>> >
>> >
>> > My understanding is that the MAX_BUFFER needs to be at least twice the
>> size
>> > of a period so I don't underrun. .periods_max means the maximum number
>> of
>> > periods in a the alsa dma_area buffer, right?
>> >
>> > So when my DMA fires its ISR, I copy from its local PING buffer to the
>> > dma_area at offset 0, increment the buf_pos by the frame_length
>> (64Bytes),
>> > and call snd_pcm_period_elapsed.
>> >
>> > My DMA fires its ISR for its local PONG buffer, copies to the
>> > dma_area+buf_pos, increments buf_pos (now back to 0, since buffer only
>> > holds 2 frames/periods), and I call snd_pcm_period_elapsed again,
>> correct?
>>
>> Hi,
>>
>> In principle sounds OK. But there is not much of a point to use a
>> ping-pong buffer if you give the real buffer the same restrictions. You
>> might as well use the dma_area buffer as the target of the DMA in that
>> case. But since in your case the DMA is very restrictive in what it can
>> support it makes more sense to use the ping-pong buffer and broaden the
>> restrictions on the real buffer. Allow larger period sizes (only call
>> snd_pcm_period_elapsed() every N interrupts), allow more than two
>> periods and so on.
>>
>> - Lars
>>
>>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-07-12  2:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-11 19:10 Verification of settings Rob Nertney
2016-07-11 19:29 ` Lars-Peter Clausen
2016-07-11 19:33   ` Rob Nertney
2016-07-12  2:00     ` Rob Nertney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).