I am trying to constrain the number of frames per period (not the number of periods). The DMA transfer creates an interrupt every 512 frames (1 frame = 16 channels with 32bits per channel) . I am having a difficult time understanding how to properly write the ALSA driver so that it will work with many different formats and between 1 and 2 channels.
Using period_bytes_min/max doesn't work for this situation; these fields are intended for hardware that has constraints on the number of bytes.
Set the snd_pcm_hardware fields so that all sample formats are supported.
I do not understand why I need to add all of the sample formats, but I went ahead and changed snd_pcm_hardware to: .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE),
In the PCM device's open callback, add another constraint by calling snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 512, 512);
Thank you! This worked as you described and the applications now select a period of 512 frames.
// the max number of bytes in one PCM stream // must allow for a minimum of 4 periods with // 512 frames per period and up to 2 channels of // 32 bit data per frame .buffer_bytes_max = 32768, // this value allows 8 periods of the max frame size
Are the minimum 4 and maximum 8 periods actual hardware constraints?
Not really. Mark Brown of WolfsonMicro helped me discover that I needed at least 3 periods so that there would always be one playing in the DMA buffer, one ready to play, and one able to be written to. I selected 4 periods as a minimum because it made it easier for me to figure out good sizes for the DMA buffer. There is no true hardware constraint on the max number of periods but I do need to keep my DMA period buffer size smaller than 64kb because the 2d transfer mode that is implemented by the blackfin BF537 sport driver (bf5xx-sport.c) doesn't seem to work properly. If I stay below 64kb it doesn't need to use 2d DMA mode.
I have had much better results after these changes but am still not 100% happy with the driver. There is still some choppiness when playing a wav file using aplay. It seems like there are some xrun conditions that occur just at the start of playback and then work themselves out. I am not sure if I have latest aplay because it came with the Blackfin distribution of uClinux. I'll look into it further. I also have some problems with the OSS emulation not working properly every time. I do not plan to use OSS in my actual application so I can ignore that for now.
Thank you Clemens and Jaroslav for your help. I will email again if I have any more questions.
-Adam