[alsa-devel] Problem with underrun on new CS42448 x2 driver
I am trying to write a driver for the Blackfin BF537 processor on a custom board that has two CS42448 CODECs connected to SPORT0. I am using TDM and there are 8 channels per frame on each data line (primary and secondary). My DMA buffer must interleave the data for the two data lines (for a total of 16 channels of data per frame). I have completed all of this and the driver will sometimes work properly but I am having underrun problems. I would like to use snd_async_add_pcm_handler as it is used in the /test/pcm.c example but it seems as though an underrun occurs at regular intervals causing the PCM prepare function to be called again (this results in a tone that sounds good but only for a short time before it stops and then starts again).
There is plenty of time for the data to be transferred. I feel as though the driver is not calling snd_pcm_period_elapsed fast enough. At the moment, I call snd_pcm_period_elapsed from within a callback function that occurs every time a DMA period elapse occurs. I have been working on this for quite a while now. Is there someone who can look at the driver code for me or provide detailed information on when ALSA expects to have snd_pcm_period_elapsed get called to avoid an underrun?
The other thing that is strange is that I have to explicitly set the period size for aplay to work. For example: aplay --period-size=1024 test.wav which gives me a period time of 21333 but when I use this period time with the /test/pcm.c sample that is provided the tone still does not sound right (although it does seem to improve)
I am about ready to bypass ALSA entirely but I hate the idea of breaking from standards (not to mention having to rewrite an entire audio interface). Any help would be greatly appreciated!
You can check out the driver here: http://www.alcorn.com/ftp/swap/ami_cs42448.zip
Thank you, Adam
Adam Rosenberg Software Engineer
Alcorn McBride Inc. 3300 South Hiawassee Building 105 Orlando, FL 32835
(407) 296 - 5800 ext. 5490
On Tue, Aug 24, 2010 at 03:47:13PM -0400, Adam Rosenberg wrote:
I am trying to write a driver for the Blackfin BF537 processor on a custom board that has two CS42448 CODECs connected to SPORT0. I am using TDM and
CCing in the Blackfin guys - this looks like a CPU specific issue. However, see below...
there are 8 channels per frame on each data line (primary and secondary). My DMA buffer must interleave the data for the two data lines (for a total of 16 channels of data per frame). I have completed all of this and the driver will sometimes work properly but I am having underrun problems. I would like to use snd_async_add_pcm_handler as it is used in the /test/pcm.c example but it seems as though an underrun occurs at regular intervals causing the PCM prepare function to be called again (this results in a tone that sounds good but only for a short time before it stops and then starts again).
There is plenty of time for the data to be transferred. I feel as though the driver is not calling snd_pcm_period_elapsed fast enough. At the moment, I call snd_pcm_period_elapsed from within a callback function that occurs every time a DMA period elapse occurs. I have been working on this for quite a while now. Is there someone who can look at the driver code for me or provide detailed information on when ALSA expects to have snd_pcm_period_elapsed get called to avoid an underrun?
The other thing that is strange is that I have to explicitly set the period size for aplay to work. For example: aplay --period-size=1024 test.wav which gives me a period time of 21333 but when I use this period time with the /test/pcm.c sample that is provided the tone still does not sound right (although it does seem to improve)
If you're needing to set the period size explicitly this probably indicates a problem with the way the constraints are being exposed to applicatiohns - normally the constraints would force an appropriate configuration to be selected.
I am about ready to bypass ALSA entirely but I hate the idea of breaking from standards (not to mention having to rewrite an entire audio interface). Any help would be greatly appreciated!
You can check out the driver here: http://www.alcorn.com/ftp/swap/ami_cs42448.zip
Please post code to the list if you want people to review it. Looking at the code there it looks like you've implemented your own custom driver entirely outside the standard ASoC framework and Blackfin drivers. It will be much easier to get community support with the standard kernel code, if you're not reusing any of the existing CPU support you're much more on your own.
Mark,
Thank you for the reply. I emailed Barry Song on July 30th to request some help moving to the new ASoC standards but received no response.
I began writing this driver on the Blackfin uClinux 2009 release and based it on the AD1836 and AD1938 drivers. I am now using the Blackfin SVN trunk and have found that the driver model was changed to ASoC. It is not apparent how I would create a driver that supports two chips off of the same SPORT using the ASoC framework.
The best I could do was use the same SPORT driver that the ASoC code uses (bf5xx-sport.c) so that I was at least up-to-date in that area. I had to modify that driver so that it would support the secondary data lines of the SPORT. I found that the driver did not function well in 2D DMA mode so I have to keep my period size below 64kb. There is also a problem with starting Rx and Tx that causes the DMA data to be placed into the SPORT multichannel window incorrectly. I added a function to the SPORT driver yesterday that can work around this problem by starting both Rx and Tx as normal then stopping the SPORT and restarting it like this:
int sport_start_both(struct sport_device *sport) { sport_tx_start(sport); msleep(1); // is this needed? sport_rx_start(sport); msleep(1); // is this needed? sport_stop(sport); msleep(1); // is this needed? sport_start(sport); return 0; } EXPORT_SYMBOL(sport_start_both);
This ensures that the data from the DMA buffer is properly loaded into the SPORT multichannel window for both the Rx and Tx data lines. If it is not done this way it seems that one of them is always being filled incorrectly. This may have sometime to do with the fact that I have to enable the secondary data lines but there is no clear explanation for why that would have an effect.
I have not entered any constraints into the driver because there really should be no need. The driver just copies whatever PCM data that is provided directly to the DMA buffer. It seems that the problem occurs because the location to copy to is based on the pos suggested by the callback function. I am still finding it difficult to tell how ALSA decides there is an underrun or overrun. I am definitely trying to read or write the pcm data fast enough but it seems as though I get these errors anyway.
Questions: 1. How do I implement an ASoC-style driver that supports multiple chips when they are connected to the same SPORT but use different SPI chip selects? 2. How do I define the proper buffer/period size constraints or should I ignore the suggested position during copy operations and just keep track of the position within the DMA buffer myself? 3. Can you suggest a good way to debug underrun/overrun problems?
Thank you, Adam
Adam Rosenberg Software Engineer
Alcorn McBride Inc. 3300 South Hiawassee Building 105 Orlando, FL 32835
(407) 296 - 5800 ext. 5490
On Thu, Aug 26, 2010 at 02:06:43PM -0400, Adam Rosenberg wrote:
Thank you for the reply. I emailed Barry Song on July 30th to request some help moving to the new ASoC standards but received no response.
Please don't top post, and remember to include context in your reply so people can understand the context of your message0. This is standard for Linux kernel mailing lists.
I have not entered any constraints into the driver because there really should be no need. The driver just copies whatever PCM data that is provided directly to the DMA buffer. It seems that the problem occurs because the location to copy to is based on the pos suggested by the callback function. I am still finding it difficult to tell how ALSA decides there is an underrun or overrun. I am definitely trying to read or write the pcm data fast enough but it seems as though I get these errors anyway.
I've no idea what "the callback function" is? As far as determining the overrun and underrun conditions goes the source is available - obviously and overrun is where you try to write more data than there's space for and an underrun is when the hardware runs out of data.
This can either mean that the driver is reporting that data is being consumed at the wrong rate (possibly as a result of hardware misconfiguration resulting in a misunderstanding about the format of incoming data, or misconfiguration of clocks) or it can mean that the application is getting confused.
Questions:
- How do I implement an ASoC-style driver that supports multiple chips
when they are connected to the same SPORT but use different SPI chip selects?
Look at current ASoC in -next, I've never tried this multi drop DAI setup directly myself but it does support multiple CODECs in the system.
- How do I define the proper buffer/period size constraints or should I
ignore the suggested position during copy operations and just keep track of the position within the DMA buffer myself?
Your constraints will flow from the requirements of the hardware plus any additional requirements that the driver you've written imposes. For example, if you always need a period of data ready to start DMA on which the application can't touch for coherency reasons then you need to make sure that there's at least three periods (running, about to run and updatable), or if your hardware DMAs in blocks you need a minimum period size for that.
- Can you suggest a good way to debug underrun/overrun problems?
There's a few settings for XRUN detection diagnostics in the ALSA core code which can be useful - see pcm_lib.c and the SND_PCM_XRUN_DEBUG config option.
Please don't top post, and remember to include context in your reply so people can understand the context of your message0. This is standard for Linux kernel mailing lists.
Thanks, no more top posts for me...
I have not entered any constraints into the driver because there really should be no need. The driver just copies whatever PCM data that is provided directly to the DMA buffer. It seems that the problem occurs because the location to copy to is based on the pos suggested by the callback function. I am still finding it difficult to tell how ALSA decides there is an underrun or overrun. I am definitely trying to read or write the pcm data fast enough but it seems as though I get these errors anyway.
I've no idea what "the callback function" is?
The callback function is the PCM copy function that I define in struct snd_pcm_ops
Questions:
- How do I implement an ASoC-style driver that supports multiple chips
when they are connected to the same SPORT but use different SPI chip selects?
Look at current ASoC in -next, I've never tried this multi drop DAI setup directly myself but it does support multiple CODECs in the system.
I could not find anything in the linux-2.6.x/sound/soc/ directory called "next" and cannot find any documentation in linux-2.6.x/Documentation/sound/alsa/soc about "multi drop"
- How do I define the proper buffer/period size constraints or should I
ignore the suggested position during copy operations and just keep track of the position within the DMA buffer myself?
Your constraints will flow from the requirements of the hardware plus any additional requirements that the driver you've written imposes. For example, if you always need a period of data ready to start DMA on which the application can't touch for coherency reasons then you need to make sure that there's at least three periods (running, about to run and updatable), or if your hardware DMAs in blocks you need a minimum period size for that.
This information was a little cryptic at first. It turns out it was the diamond in the rough though. I set periods_min in struct snd_pcm_hardware to 3 and it solved quite a few underrun problems.
Question: Is there a way I can force ALSA to always use a period size that is a multiple of 16?
- Can you suggest a good way to debug underrun/overrun problems?
There's a few settings for XRUN detection diagnostics in the ALSA core code which can be useful - see pcm_lib.c and the SND_PCM_XRUN_DEBUG config option.
Thank you for this tip. It turns out you need to enable SND_VERBOSE_PROCFS to see this option in the kernel configuration. I am hoping this additional debug information may help me to figure out why plughw has never been able to properly convert the sample rate for me.
Thanks and have a great weekend, Adam
On Fri, Aug 27, 2010 at 04:11:48PM -0400, Adam Rosenberg wrote:
I have not entered any constraints into the driver because there really should be no need. The driver just copies whatever PCM data that is provided directly to the DMA buffer. It seems that the problem occurs because the location to copy to is based on the pos suggested by the callback function. I am still finding it difficult to tell how ALSA decides there is an underrun or overrun. I am definitely trying to read or write the pcm data fast enough but it seems as though I get these errors anyway.
I've no idea what "the callback function" is?
The callback function is the PCM copy function that I define in struct snd_pcm_ops
So, this will be decided based on how much data ALSA thinks is being consumed and how much it thinks can be
Questions:
- How do I implement an ASoC-style driver that supports multiple chips
when they are connected to the same SPORT but use different SPI chip selects?
Look at current ASoC in -next, I've never tried this multi drop DAI setup directly myself but it does support multiple CODECs in the system.
I could not find anything in the linux-2.6.x/sound/soc/ directory called "next" and cannot find any documentation in linux-2.6.x/Documentation/sound/alsa/soc about "multi drop"
-next is Stephen Rothewell's linux-next tree which contains the latest development versions of all the trees that are likely to go into Linux at the next merge window.
The documenation is bitrotted here but you're looking for the recent multi-component changes.
- How do I define the proper buffer/period size constraints or should I
ignore the suggested position during copy operations and just keep track of the position within the DMA buffer myself?
Your constraints will flow from the requirements of the hardware plus any additional requirements that the driver you've written imposes. For example, if you always need a period of data ready to start DMA on which the application can't touch for coherency reasons then you need to make sure that there's at least three periods (running, about to run and updatable), or if your hardware DMAs in blocks you need a minimum period size for that.
This information was a little cryptic at first. It turns out it was the diamond in the rough though. I set periods_min in struct snd_pcm_hardware to 3 and it solved quite a few underrun problems.
Right, so this means that previously you were not getting as much data as you needed buffered by your application so when the driver ran out of data to feed to the hardware the application hadn't provided any.
Question: Is there a way I can force ALSA to always use a period size that is a multiple of 16?
You're looking for
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
I suspect but ICBW - it'll be one of the snd_pcm_hw_constraint_() functions. Take a look at what other drivers are doing with this sort of stuff.
On Thu, Aug 26, 2010 at 14:06, Adam Rosenberg wrote:
Thank you for the reply. I emailed Barry Song on July 30th to request some help moving to the new ASoC standards but received no response.
developers shouldnt be e-mailed directly ... it isnt uncommon for them to simply be punted. this is why we have mailing lists and forums.
I began writing this driver on the Blackfin uClinux 2009 release and based it on the AD1836 and AD1938 drivers. I am now using the Blackfin SVN trunk and have found that the driver model was changed to ASoC. It is not apparent how I would create a driver that supports two chips off of the same SPORT using the ASoC framework.
The best I could do was use the same SPORT driver that the ASoC code uses (bf5xx-sport.c) so that I was at least up-to-date in that area. I had to modify that driver so that it would support the secondary data lines of the SPORT. I found that the driver did not function well in 2D DMA mode so I have to keep my period size below 64kb. There is also a problem with starting Rx and Tx that causes the DMA data to be placed into the SPORT multichannel window incorrectly. I added a function to the SPORT driver yesterday that can work around this problem by starting both Rx and Tx as normal then stopping the SPORT and restarting it like this:
int sport_start_both(struct sport_device *sport) { sport_tx_start(sport); msleep(1); // is this needed? sport_rx_start(sport); msleep(1); // is this needed? sport_stop(sport); msleep(1); // is this needed? sport_start(sport); return 0; } EXPORT_SYMBOL(sport_start_both);
This ensures that the data from the DMA buffer is properly loaded into the SPORT multichannel window for both the Rx and Tx data lines. If it is not done this way it seems that one of them is always being filled incorrectly. This may have sometime to do with the fact that I have to enable the secondary data lines but there is no clear explanation for why that would have an effect.
I have not entered any constraints into the driver because there really should be no need. The driver just copies whatever PCM data that is provided directly to the DMA buffer. It seems that the problem occurs because the location to copy to is based on the pos suggested by the callback function. I am still finding it difficult to tell how ALSA decides there is an underrun or overrun. I am definitely trying to read or write the pcm data fast enough but it seems as though I get these errors anyway.
Questions: 1. How do I implement an ASoC-style driver that supports multiple chips when they are connected to the same SPORT but use different SPI chip selects? 2. How do I define the proper buffer/period size constraints or should I ignore the suggested position during copy operations and just keep track of the position within the DMA buffer myself? 3. Can you suggest a good way to debug underrun/overrun problems?
i dont really know ASoC/SPORTs, so we'd have to get someone to look into it -mike
On Fri, Aug 27, 2010 at 04:37:45PM -0400, Mike Frysinger wrote:
On Thu, Aug 26, 2010 at 14:06, Adam Rosenberg wrote:
Thank you for the reply. I emailed Barry Song on July 30th to request some help moving to the new ASoC standards but received no response.
developers shouldnt be e-mailed directly ... it isnt uncommon for them to simply be punted. this is why we have mailing lists and forums.
That's shouldn't *only* be e-mailed directly (for Linux stuff). You should generally keep the relevant folks in the CC as well but also mail the lists concerned. The direct mail is there because the lists can be high volume so it helps people see the mail, while the lists mean that people other than those you thought of will be able to help and that any answers will be archived for other people who might need them.
On Friday, August 27, 2010 17:20:25 Mark Brown wrote:
On Fri, Aug 27, 2010 at 04:37:45PM -0400, Mike Frysinger wrote:
On Thu, Aug 26, 2010 at 14:06, Adam Rosenberg wrote:
Thank you for the reply. I emailed Barry Song on July 30th to request some help moving to the new ASoC standards but received no response.
developers shouldnt be e-mailed directly ... it isnt uncommon for them to simply be punted. this is why we have mailing lists and forums.
That's shouldn't *only* be e-mailed directly (for Linux stuff). You should generally keep the relevant folks in the CC as well but also mail the lists concerned. The direct mail is there because the lists can be high volume so it helps people see the mail, while the lists mean that people other than those you thought of will be able to help and that any answers will be archived for other people who might need them.
right of course. i meant e-mailing people directly and not including lists.
for Blackfin issues, we have a mailing list that should always be CC-ed whenever the Blackfin is involved. -mike
participants (3)
-
Adam Rosenberg
-
Mark Brown
-
Mike Frysinger