[alsa-devel] snd_pcm_hardware_t.info question
Hi all, I am trying to fix (improve?) a driver for an embedded ARM device I bought months ago, and for some reasons some ALSA applications work fine while other ones don't...
Looking at the driver I got, I noticed that the info field in the snd_pcm_hardware_t struct just defines:
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE
while the info in the tutorial "writing an alsa driver" defines:
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID
Furthermore, the driver defines a copy callback (actually 2, one for playback and one for capture), where it copies the data from the use space to the dma buffer. Since the dma buffer was preallocated with snd_pcm_lib_preallocate_pages_for_all and is accessible from the "outside", I wonder why the original author did this...
I have some questions for you gurus:
- what is the difference between SNDRV_PCM_INFO_MMAP and SNDRV_PCM_INFO_MMAP_VALID? What is SNDRV_PCM_INFO_BLOCK_TRANSFER?
- The code calls snd_pcm_lib_preallocate_pages_for_all function as following:
/* allocate the pcm(DMA) memory */ ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,0, 4*128*1024, 4*128*1024);
is the DMA_TYPE right for an ARM device? Is NULL a correct value for data in this case?
- In case I get rid of the copy callback, how do I specify the format of the stream? How does Where can I find an example for that?
Thanks a lot Andrea
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
At Tue, 17 Apr 2007 01:03:24 -0700 (PDT), Ciaccia wrote:
Hi all, I am trying to fix (improve?) a driver for an embedded ARM device I bought months ago, and for some reasons some ALSA applications work fine while other ones don't...
Looking at the driver I got, I noticed that the info field in the snd_pcm_hardware_t struct just defines:
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE
while the info in the tutorial "writing an alsa driver" defines:
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID
Furthermore, the driver defines a copy callback (actually 2, one for playback and one for capture), where it copies the data from the use space to the dma buffer. Since the dma buffer was preallocated with snd_pcm_lib_preallocate_pages_for_all and is accessible from the "outside", I wonder why the original author did this...
I have some questions for you gurus:
- what is the difference between SNDRV_PCM_INFO_MMAP
and SNDRV_PCM_INFO_MMAP_VALID? What is SNDRV_PCM_INFO_BLOCK_TRANSFER?
MMAP flag is a very important flag. This indicates that the driver can work on mmap mode. If not given, no mmap is allowed.
Meanwhile, MMAP_VALID and BLOCK_TRANSFER flags are only for kernel-OSS emulation. For ALSA native apps, they have no meaning. MMAP_VALID is necessary for allowing OSS mmap mode. BLOCK_TRANSFER is specified, it resets REALTIME capability in OSS ioctl.
- The code calls snd_pcm_lib_preallocate_pages_for_all
function as following:
/* allocate the pcm(DMA) memory */ ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,0, 4*128*1024, 4*128*1024);
is the DMA_TYPE right for an ARM device? Is NULL a correct value for data in this case?
No, it should pass the device pointer there. Also make sure that snd_pcm_lib_malloc() is actually used in hw_params callback. Otherwise, pre-allocation makes no sense.
- In case I get rid of the copy callback, how do I
specify the format of the stream? How does Where can I find an example for that?
The available formats are specified snd_pcm_hardware formats. Then in prepare callback, you can get the specified format by the application via runtime->format field.
I don't understand the rest question in the above. But, note that the copy callback isn't used at all in mmap mode. The copy/silenece callbacks are for read/write mode. When the app mmaps the buffer, it means that the buffer is directly accessible without read/write calls. So, it skips copy and silence callbacks. If any copy operation is needed, the driver itself has to do in some way, e.g. in background task or in ack callback.
HTH,
Takashi
Hi Takashi, Thanks for your explanation. My request was not clear, since my understanding of ALSA is lacking and I need to understand more...
The driver I currently have is here: http://www.pecore.ch/test/ep93xx-i2s.c.txt
It's really messy, it performs all the format conversions in the driver (they could be done in the alsa-lib) and it lacks some functionalities, so I would like to make it shorter, better and more readable.
The driver does not currently define SNDRV_PCM_INFO_MMAP and the memory is copied in the copy callback. I would like to delete the copy callback (which is not really used), since the samples could be written directly to the dma buffer by alsa-lib.
How does alsa-lib know how to store the samples in the dma-buffer? How does alsa-lib know that the samples are interleaved, occupy 32 bits each one (even if the format is 24 bits) and that the left channel samples are at index #0 and the left ones at index #1? Or that between two consecutive samples in mono there should be a 4 bytes gap?
I suppose this is set in the formats filed of the snd_pcm_hardware_t struct, but I did not find a clear explanation of that...
Thanks again Andrea
--- Takashi Iwai tiwai@suse.de wrote:
At Tue, 17 Apr 2007 01:03:24 -0700 (PDT), Ciaccia wrote:
Hi all, I am trying to fix (improve?) a driver for an
embedded
ARM device I bought months ago, and for some
reasons
some ALSA applications work fine while other ones don't...
Looking at the driver I got, I noticed that the
info
field in the snd_pcm_hardware_t struct just
defines:
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE
while the info in the tutorial "writing an alsa driver" defines:
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID
Furthermore, the driver defines a copy callback (actually 2, one for playback and one for
capture),
where it copies the data from the use space to the
dma
buffer. Since the dma buffer was preallocated with snd_pcm_lib_preallocate_pages_for_all and is accessible from the "outside", I wonder why the original author did this...
I have some questions for you gurus:
- what is the difference between
SNDRV_PCM_INFO_MMAP
and SNDRV_PCM_INFO_MMAP_VALID? What is SNDRV_PCM_INFO_BLOCK_TRANSFER?
MMAP flag is a very important flag. This indicates that the driver can work on mmap mode. If not given, no mmap is allowed.
Meanwhile, MMAP_VALID and BLOCK_TRANSFER flags are only for kernel-OSS emulation. For ALSA native apps, they have no meaning. MMAP_VALID is necessary for allowing OSS mmap mode. BLOCK_TRANSFER is specified, it resets REALTIME capability in OSS ioctl.
- The code calls
snd_pcm_lib_preallocate_pages_for_all
function as following:
/* allocate the pcm(DMA) memory */ ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,0, 4*128*1024, 4*128*1024);
is the DMA_TYPE right for an ARM device? Is NULL a correct value for data in this case?
No, it should pass the device pointer there. Also make sure that snd_pcm_lib_malloc() is actually used in hw_params callback. Otherwise, pre-allocation makes no sense.
- In case I get rid of the copy callback, how do I
specify the format of the stream? How does Where
can I
find an example for that?
The available formats are specified snd_pcm_hardware formats. Then in prepare callback, you can get the specified format by the application via runtime->format field.
I don't understand the rest question in the above. But, note that the copy callback isn't used at all in mmap mode. The copy/silenece callbacks are for read/write mode. When the app mmaps the buffer, it means that the buffer is directly accessible without read/write calls. So, it skips copy and silence callbacks. If any copy operation is needed, the driver itself has to do in some way, e.g. in background task or in ack callback.
HTH,
Takashi
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
At Tue, 17 Apr 2007 04:36:28 -0700 (PDT), Ciaccia wrote:
Hi Takashi, Thanks for your explanation. My request was not clear, since my understanding of ALSA is lacking and I need to understand more...
The driver I currently have is here: http://www.pecore.ch/test/ep93xx-i2s.c.txt
It's really messy, it performs all the format conversions in the driver (they could be done in the alsa-lib) and it lacks some functionalities, so I would like to make it shorter, better and more readable.
The driver does not currently define SNDRV_PCM_INFO_MMAP and the memory is copied in the copy callback. I would like to delete the copy callback (which is not really used), since the samples could be written directly to the dma buffer by alsa-lib.
How does alsa-lib know how to store the samples in the dma-buffer?
Based on the information the driver gives: access, formats, channels, etc.
How does alsa-lib know that the samples are interleaved,
access has SNDRV_PCM_ACCESS_{MMAP|RW}_INTERLEAVED.
occupy 32 bits each one (even if the format is 24 bits) and that the left channel samples are at index #0 and the left ones at index #1?
formats has SNDRV_PCM_FMTBIT_S16_{LE|BE}.
Or that between two consecutive samples in mono there should be a 4 bytes gap?
It's possible to support a non-standard stream like that, but it's a bit complicated. So, I recommend not to support this first (i.e. channels_max = channels_min = 2). Then alsa-lib will copy the mono stream automatically to stereo.
Takashi
Takashi, I look through the code, I found some interesting examples...
Instead of defining a 2 as a min number of channel, could I use the following code?
static int ep93xx_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) { struct snd_pcm_channel_info *info=arg; info->offset = 0; info->first = info->channel * 32; info->step = 64; return 0; }
return snd_pcm_lib_ioctl(substream, cmd, arg); }
Would that work? Or should I always support stereo even when not needed?
Ciao Andrea
--- Takashi Iwai tiwai@suse.de wrote:
At Tue, 17 Apr 2007 04:36:28 -0700 (PDT), Ciaccia wrote:
Hi Takashi, Thanks for your explanation. My request was not
clear,
since my understanding of ALSA is lacking and I
need
to understand more...
The driver I currently have is here: http://www.pecore.ch/test/ep93xx-i2s.c.txt
It's really messy, it performs all the format conversions in the driver (they could be done in
the
alsa-lib) and it lacks some functionalities, so I would like to make it shorter, better and more readable.
The driver does not currently define SNDRV_PCM_INFO_MMAP and the memory is copied in
the
copy callback. I would like to delete the copy callback (which is not really used), since the
samples
could be written directly to the dma buffer by alsa-lib.
How does alsa-lib know how to store the samples in
the
dma-buffer?
Based on the information the driver gives: access, formats, channels, etc.
How does alsa-lib know that the samples are interleaved,
access has SNDRV_PCM_ACCESS_{MMAP|RW}_INTERLEAVED.
occupy 32 bits each one (even if the format is 24 bits) and that the left channel
samples
are at index #0 and the left ones at index #1?
formats has SNDRV_PCM_FMTBIT_S16_{LE|BE}.
Or that between two consecutive samples in mono there
should
be a 4 bytes gap?
It's possible to support a non-standard stream like that, but it's a bit complicated. So, I recommend not to support this first (i.e. channels_max = channels_min = 2). Then alsa-lib will copy the mono stream automatically to stereo.
Takashi
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
At Wed, 18 Apr 2007 07:14:42 -0700 (PDT), Ciaccia wrote:
Takashi, I look through the code, I found some interesting examples...
Instead of defining a 2 as a min number of channel, could I use the following code?
static int ep93xx_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) { struct snd_pcm_channel_info *info=arg; info->offset = 0; info->first = info->channel * 32; info->step = 64; return 0; }
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
Would that work? Or should I always support stereo even when not needed?
Yes, this would work. But, I'm not sure whether all apps work well with this setting because this feature is used by only few drivers. So, I recommend first try to use the stereo only, then try this after that.
Takashi
Ciao Andrea
--- Takashi Iwai tiwai@suse.de wrote:
At Tue, 17 Apr 2007 04:36:28 -0700 (PDT), Ciaccia wrote:
Hi Takashi, Thanks for your explanation. My request was not
clear,
since my understanding of ALSA is lacking and I
need
to understand more...
The driver I currently have is here: http://www.pecore.ch/test/ep93xx-i2s.c.txt
It's really messy, it performs all the format conversions in the driver (they could be done in
the
alsa-lib) and it lacks some functionalities, so I would like to make it shorter, better and more readable.
The driver does not currently define SNDRV_PCM_INFO_MMAP and the memory is copied in
the
copy callback. I would like to delete the copy callback (which is not really used), since the
samples
could be written directly to the dma buffer by alsa-lib.
How does alsa-lib know how to store the samples in
the
dma-buffer?
Based on the information the driver gives: access, formats, channels, etc.
How does alsa-lib know that the samples are interleaved,
access has SNDRV_PCM_ACCESS_{MMAP|RW}_INTERLEAVED.
occupy 32 bits each one (even if the format is 24 bits) and that the left channel
samples
are at index #0 and the left ones at index #1?
formats has SNDRV_PCM_FMTBIT_S16_{LE|BE}.
Or that between two consecutive samples in mono there
should
be a 4 bytes gap?
It's possible to support a non-standard stream like that, but it's a bit complicated. So, I recommend not to support this first (i.e. channels_max = channels_min = 2). Then alsa-lib will copy the mono stream automatically to stereo.
Takashi
Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
participants (2)
-
Ciaccia
-
Takashi Iwai