tinyalsa timing and problems with PCM_MMAP

1k Views Asked by At

We're on an ARM64 Snapdragon using a Qualcomm PM8916 codec. The goal is to sample a single channel at 48000 samps/sec, and to use high resolution time stamps. The tinyalsa docs insist that we must use PCM_MMAP. When we do, the pcm_open() does not complain, but pcm_readi() fails errno:22 Invalid argument in the ioctl().

Another symptom that I believe is related is that when pcm_open is called in this form (no PCM_MMAP):

tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN, &cfg );

Audio flows wonderfully (period=256), and contrary to the docs pcm_get_htimestamp() returns values just fine. Not sure how accurate the timing is, but tomorrow I will inject GPS 1PPS and do my standard test to figure that out. But when I follow instructions and use PCM_MMAP, eg:

tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN | PCM_MMAP | PCM_MONOTONIC | PCM_NOIRQ, &cfg );

or

tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN | PCM_MMAP | PCM_NONBLOCK, &cfg );    

The read fails as mentioned above. I haven't tried every possible combination, but that's coming. The odd thing is that the whenever PCM_MMAP is specified, the time stamps that

int err = pcm_get_htimestamp( tinyHandle, &available, &timestamp);

returns become non-sensical, and tv_sec contains values circa 4917 or 5013 instead of a reasonable time_t. I'd be tempted to conclude that the tv_sec values are elapsed time since launch, except that the timestamps happen within seconds of launch.

Oh, one other detail. The PCM_NONBLOCK option was not recognized in the version of tinyalsa supplied with the sdk I have been using. So I git cloned tinyalsa, built a static lib, and upgraded to the latest and greatest. The problem I have with PCM_MMAP persists in both versions. This, coupled with the fact that hours of searching for people with the same problem has been largely a bust, leads me to believe that it is something about our new product and not about the libs.

Any thoughts about where to look next?

Thanks!

Confirmed this morning that the ioctl inside pcm_readi() is receiving the proper file descriptor (4) and period size (256). There are no other arguments that could be invalid

1

There are 1 best solutions below

0
On

OK, GPS 1PPS test shows timestamp accuracy on the order of 2-3msec, which gets us going "enough" with this usage (no PCM_MMAP):

tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN, &cfg );

Here is the comment that sent me down the rabbit hole:

/** Returns available frames in pcm buffer and corresponding time stamp.
 * The clock is CLOCK_MONOTONIC if flag @ref PCM_MONOTONIC was specified in @ref pcm_open,
 * otherwise the clock is CLOCK_REALTIME.
 * For an input stream, frames available are frames ready for the application to read.
 * For an output stream, frames available are the number of empty frames available for the application to write.
 * Only available for PCMs opened with the @ref PCM_MMAP flag.
 * @param pcm A PCM handle.
 * @param avail The number of available frames
 * @param tstamp The timestamp
 * @return On success, zero is returned; on failure, negative one.
 */
int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
                       struct timespec *tstamp)

It is misleading, as it deterred me from trying the pcm_get_htimestamp() call without PCM_MMAP working. There will be further investigations, and if I can post them, I will.

Thank you!