[alsa-devel] How to enforce 32bit access?
Hi ALSA devs,
(based on a Xilinx ML403, PPC405, OPB bus) I have a custom sound controller, which allows 32bit write accesses to its IO memory, only. The controller supports S16_LE, S16_BE, U16_LE, U16_BE with min. and max. 2 channels (stereo), only! => So a frame has to be 32bits wide and one frame has to be written at one point of time (= one 32bit bus access).
Now, playing a 16kHz, S16_LE, Mono .wav-file with aplay invokes the conversion framework of the alsa-lib. The following line of code (of pcm_plugin.h) is executed:
conv_xx12_xx12: as_u16(dst) = as_u16c(src);
This is a 16bit access and thus fails with a Bus error/Kernel Oops.
Therefore my question is:
In my driver for the controller, how do I tell ALSA, that it is only allowed to write in 32bit quantities? Is this possible at all? Or do I have to use a special .asoundrc file?
Thanks, Joachim
PS: 16bit, signed/unsigned, LE/BE, stereo (!) .wav files can be played without any problem.
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
On Tue, 2007-10-02 at 17:34 +0200, Joachim Foerster wrote:
[...]
Therefore my question is:
In my driver for the controller, how do I tell ALSA, that it is only allowed to write in 32bit quantities? Is this possible at all? Or do I have to use a special .asoundrc file?
Thanks, Joachim
At Fri, 05 Oct 2007 19:09:53 +0200, Joachim Foerster wrote:
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
Takashi
On Tue, 2007-10-02 at 17:34 +0200, Joachim Foerster wrote:
[...]
Therefore my question is:
In my driver for the controller, how do I tell ALSA, that it is only allowed to write in 32bit quantities? Is this possible at all? Or do I have to use a special .asoundrc file?
Thanks, Joachim
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Hi Takashi,
On Tue, 2007-10-09 at 11:08 +0200, Takashi Iwai wrote:
At Fri, 05 Oct 2007 19:09:53 +0200, Joachim Foerster wrote:
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
bash-3.00# aplay -v -M ../Absage.wav Playing WAVE '../Absage.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono Plug PCM: Route conversion PCM (sformat=S16_LE) Transformation table: 0 <- 0 1 <- 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 1 rate : 16000 exact rate : 16000 (16000/1) msbits : 16 buffer_size : 4096 period_size : 1024 period_time : 64000 tick_time : 4000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 1024 xfer_align : 1024 start_threshold : 4096 stop_threshold : 4096 silence_threshold: 0 silence_size : 0 boundary : 1073741824 Slave: Hardware PCM card 0 'Lorenz' AC97 Digital Controller' device 0 subdevice 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : 16000 exact rate : 16000 (16000/1) msbits : 16 buffer_size : 4096 period_size : 1024 period_time : 64000 tick_time : 4000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 1024 xfer_align : 1024 start_threshold : 4096 stop_threshold : 4096 silence_threshold: 0 silence_size : 0 boundary : 1073741824 Bus error
The kernel messages because of the bus error are: [22592.313922] Data machine check in kernel mode. [22592.318321] Oops: machine check, sig: 7 [#1] [22592.322552] NIP: c0003478 LR: c0003304 CTR: 0ff6c988 [22592.327482] REGS: c0230f50 TRAP: 0202 Not tainted (2.6.23-rc2-g2f9f7e35-dirty) [22592.334901] MSR: 00029030 <EE,ME,IR,DR> CR: 22008084 XER: 00000000 [22592.341213] TASK = c3d82420[1049] 'aplay' THREAD: c2354000 [22592.346476] GPR00: 00000000 c2355f40 c3d82420 00004000 c2355e28 00000000 00000000 00030002 [22592.354769] GPR08: c3d82764 00000002 00029032 00000000 10020000 100254ac 00000000 10020000 [22592.363063] GPR16: 7fa4c480 7fa4c58c 00000001 7fa4c4a0 00000400 7fa4c460 00000001 00000000 [22592.371357] GPR24: 00000000 0ff6c988 00000002 00000004 000003fc 1002c6d0 0ffe6b1c 3001e010 [22592.379823] NIP [c0003478] do_user_signal+0x8/0xc4 [22592.384576] LR [c0003304] ret_from_crit_exc+0x0/0xf8 [22592.389498] Call Trace: [22592.391922] [c2355f40] [c0003304] ret_from_crit_exc+0x0/0xf8 (unreliable) [22592.398655] Instruction dump: [22592.401595] 4819ae75 3d400002 614a1032 7d400124 54290024 81290028 71200004 40a2ffdc [22592.409282] 71200002 4182fe14 614a8000 7d400124 <806100b0> 70600001 41820058 91a10044
But don't think that they are very useful. They occur as soon as the alsa-lib reaches the line I described in my first mail.
Joachim
At Wed, 10 Oct 2007 15:19:42 +0200, Joachim Foerster wrote:
Hi Takashi,
On Tue, 2007-10-09 at 11:08 +0200, Takashi Iwai wrote:
At Fri, 05 Oct 2007 19:09:53 +0200, Joachim Foerster wrote:
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
bash-3.00# aplay -v -M ../Absage.wav Playing WAVE '../Absage.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
Well, the sample itself is 16bit format, and your hardware *does* support 16bit format. Why to be 32bit?
Takashi
On Wed, 2007-10-10 at 15:22 +0200, Takashi Iwai wrote:
At Fri, 05 Oct 2007 19:09:53 +0200, Joachim Foerster wrote:
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
bash-3.00# aplay -v -M ../Absage.wav Playing WAVE '../Absage.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
Well, the sample itself is 16bit format, and your hardware *does* support 16bit format. Why to be 32bit?
Well actually, we are on a embedded system here. The bus is 32bit wide (Xilinx ML403, PowerPC 405, OBP). So, why waste resources with two 16bit accesses? One sample is 16bits. But we have two channels (stereo only). Thus the controller expects a frame with 32bit data - two samples at the same time.
Joachim
PS: As soon as stereo .wav-files are used, there is no problem, because then the "conversion framework" and the Plug PCM are not used - just a plain memcpy which results in 32bit accesses.
At Wed, 10 Oct 2007 17:40:08 +0200, Joachim Foerster wrote:
On Wed, 2007-10-10 at 15:22 +0200, Takashi Iwai wrote:
At Fri, 05 Oct 2007 19:09:53 +0200, Joachim Foerster wrote:
Hi ALSA devs,
meanwhile I tried to put a constraint on SNDRV_PCM_HW_PARAM_FRAME_BITS by the use of snd_pcm_hw_constraint_minmax() function with min=32 and max=32, but still no success - the ALSA Library still makes 16bit accesses, when playing mono (1 channel) files.
Any ideas?
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
bash-3.00# aplay -v -M ../Absage.wav Playing WAVE '../Absage.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
Well, the sample itself is 16bit format, and your hardware *does* support 16bit format. Why to be 32bit?
Well actually, we are on a embedded system here. The bus is 32bit wide (Xilinx ML403, PowerPC 405, OBP). So, why waste resources with two 16bit accesses?
Because you programmed in such a way :)
One sample is 16bits. But we have two channels (stereo only). Thus the controller expects a frame with 32bit data - two samples at the same time.
Joachim
PS: As soon as stereo .wav-files are used, there is no problem, because then the "conversion framework" and the Plug PCM are not used - just a plain memcpy which results in 32bit accesses.
The problem is that the driver still accepts the 16bit format mono stream. That's what I pointed in my previous post. There is no format conversion in alsa-lib at all. It's only channel expansion from mono to stereo. The hardware accepts 16bit stereo. So, there is nothing wrong from this viewpoint.
Maybe it's not about plugin but a problem of mmap with your device?
Plug PCM: Route conversion PCM (sformat=S16_LE) Transformation table: 0 <- 0 1 <- 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 1 rate : 16000 exact rate : 16000 (16000/1) msbits : 16 buffer_size : 4096 period_size : 1024 period_time : 64000 tick_time : 4000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 1024 xfer_align : 1024 start_threshold : 4096 stop_threshold : 4096 silence_threshold: 0 silence_size : 0 boundary : 1073741824 Slave: Hardware PCM card 0 'Lorenz' AC97 Digital Controller' device 0 subdevice 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : 16000 exact rate : 16000 (16000/1) msbits : 16 buffer_size : 4096 period_size : 1024 period_time : 64000 tick_time : 4000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 1024 xfer_align : 1024 start_threshold : 4096 stop_threshold : 4096 silence_threshold: 0 silence_size : 0 boundary : 1073741824
Takashi
On Thu, 2007-10-11 at 10:50 +0200, Takashi Iwai wrote:
Could you show the chain of plugins via aplay -v ? I'm not sure which plugin requires S16. Possibly, the rate converter.
bash-3.00# aplay -v -M ../Absage.wav Playing WAVE '../Absage.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
Well, the sample itself is 16bit format, and your hardware *does* support 16bit format. Why to be 32bit?
Well actually, we are on a embedded system here. The bus is 32bit wide (Xilinx ML403, PowerPC 405, OBP). So, why waste resources with two 16bit accesses?
Because you programmed in such a way :)
Ok, then I have to change the code ... but where? ;-)
One sample is 16bits. But we have two channels (stereo only). Thus the controller expects a frame with 32bit data - two samples at the same time.
Joachim
PS: As soon as stereo .wav-files are used, there is no problem, because then the "conversion framework" and the Plug PCM are not used - just a plain memcpy which results in 32bit accesses.
The problem is that the driver still accepts the 16bit format mono stream. That's what I pointed in my previous post. There is no format conversion in alsa-lib at all. It's only channel expansion
from mono to stereo. The hardware accepts 16bit stereo. So, there is
nothing wrong from this viewpoint.
By "conversion framework" I actually meant the channel expansion - code which somehow "works in the data" before sending it to the hardware.
And yes, 16 bit samples are the only sample format supported by the hardware. But "by design of the hardware" the smallest write access has to be 32 bit wide (2 samples, stereo only)
Maybe it's not about plugin but a problem of mmap with your device?
Well, as I said before, as soon as I use a stereo .wav-file a simple call to memcpy() is used by alsa-lib to transfer the data to the hardware (snd_pcm_area_copy(), pcm.c, ca. line 2551, alsa-lib 1.0.14a). In this case the PCM Plugin isn't used at all - the output of aplay -v looks like:
Playing WAVE 'music.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo Plug PCM: Hardware PCM card 0 'Lorenz' AC97 Digital Controller' device 0 subdevice 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : 44100 exact rate : 44100 (44100/1) msbits : 16 buffer_size : 4096 period_size : 1024 period_time : 23219 tick_time : 4000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 1024 xfer_align : 1024 start_threshold : 4096 stop_threshold : 4096 silence_threshold: 0 silence_size : 0 boundary : 1073741824
So mmap on the controller's memory works - using 32 bit accesses only. And at that place in alsa-lib, I never saw an amount of data which is _not_ a multiple of 32 bits - or this just a coincidence?
So, do I understand you right, when I say: an ALSA driver does _not_ hav ethe possibility to force alsa-lib to write 32 bit entities, only?
I guess, we have to change the hardware here - it's an FPGA, so that's not a problem in principle - but it complicates the hardware, making it accept 16bit accesses.
Joachim
On Thu, 11 Oct 2007, Joachim Foerster wrote:
On Thu, 2007-10-11 at 10:50 +0200, Takashi Iwai wrote:
The problem is that the driver still accepts the 16bit format mono stream. That's what I pointed in my previous post. There is no format conversion in alsa-lib at all. It's only channel expansion
from mono to stereo. The hardware accepts 16bit stereo. So, there is
nothing wrong from this viewpoint.
By "conversion framework" I actually meant the channel expansion - code which somehow "works in the data" before sending it to the hardware.
And yes, 16 bit samples are the only sample format supported by the hardware. But "by design of the hardware" the smallest write access has to be 32 bit wide (2 samples, stereo only)
[...]
So, do I understand you right, when I say: an ALSA driver does _not_ hav ethe possibility to force alsa-lib to write 32 bit entities, only?
Joachim, it sounds like your alsa driver memory maps your device's memory buffer? And since this buffer is not normal system memory, it cannot be necessarily be accessed the same way. In this case, it only supports 32-bit accesses.
ALSA doesn't put any requirements on a mmaped sound buffer. I think most hardware has the buffer in system memory and uses DMA, so there aren't any requirements about how to access it.
Even if alsa-lib only did 32-bit accesses, any random userspace program using mmap mode might do 16 or 8 or un-aligned or whatever.
One could add a flag to ALSA for this, SNDRV_PCM_INFO_MMAP_32BIT, that means the mmap area must be accessed with aligned 32-bit (or more?) operations. But no software knows about this (yet), and it sounds like you've got the only hardware that needs it.
You could modify your driver so that it no longer supports mmap. You would need to create a bounce buffer in system memory (ALSA has code for this) and then your driver will copy from the bounce buffer into your device memory. Of course, this is less efficient and will have more latency.
It sounds like when alsa-lib does mono to stereo conversion, it does two 16 bit writes instead of one 32 bit. Duplicating the 16-bit data in a register and doing one 32 bit write should be faster. Regardless of your deivce, this seems like a good optimization to make. I know modern x86 processors don't like combining 16 and 32 bit access to the same memory; it causes partial memory stalls.
Maybe you could make this optimization to alsa-lib, and then your device would work well enough for your needs?
participants (3)
-
Joachim Foerster
-
Takashi Iwai
-
Trent Piepho