[alsa-devel] How do I tell ALSA that my driver supports every possible sample rate?
I'm building an ASOC driver, and I want to tell ALSA that my PCM and my I2S drivers support every possible sample rate, because it's the codec that determines the real limitations. What SNDRV_PCM_RATE_xxx bit-pattern do I specify that will always match?
On Mon, 2007-07-23 at 10:54 -0500, Timur Tabi wrote:
I'm building an ASOC driver, and I want to tell ALSA that my PCM and my I2S drivers support every possible sample rate, because it's the codec that determines the real limitations. What SNDRV_PCM_RATE_xxx bit-pattern do I specify that will always match?
If your lucky enough to have this hardware, I think I would probably set the I2S and DMA rates as SNDRV_PCM_RATE_8000_192000.
Liam
Liam Girdwood wrote:
If your lucky enough to have this hardware, I think I would probably set the I2S and DMA rates as SNDRV_PCM_RATE_8000_192000.
The problem is that this option only lists a selection of bit rates, and this particular macro also skips 5512 Hz. I'm looking for something that's future-proof.
I was thinking perhaps "(u32) -1", but this also turns on SNDRV_PCM_RATE_KNOT, and don't you need to have some kind of callback function for KNOT?
BTW, I'm not sure why you say if I'm lucky enough. The PCM driver, for instance, is just a front-end to the DMA controller. DMA obviously doesn't care about sample rates, so it makes sense that most PCM drivers can handle any rate. Or am I missing something?
On Mon, 2007-07-23 at 12:06 -0500, Timur Tabi wrote:
BTW, I'm not sure why you say if I'm lucky enough. The PCM driver, for instance, is just a front-end to the DMA controller. DMA obviously doesn't care about sample rates, so it makes sense that most PCM drivers can handle any rate. Or am I missing something?
Some Audio DMA controllers may not have the bandwidth for the faster rates and larger frames. Iirc, pxa255 stuttered a lot with rates > 96k.
Liam
Timur Tabi wrote:
I'm building an ASOC driver, and I want to tell ALSA that my PCM and my I2S drivers support every possible sample rate, because it's the codec that determines the real limitations. What SNDRV_PCM_RATE_xxx bit-pattern do I specify that will always match?
To indicate that the PCM device supports all sample rates between the minimum and the maximum, set SNDRV_PCM_RATE_CONTINUOUS in addition to the other supported bits.
However, in your case these bits should be set according to the capabilities of the codec.
HTH Clemens
Clemens Ladisch wrote:
To indicate that the PCM device supports all sample rates between the minimum and the maximum, set SNDRV_PCM_RATE_CONTINUOUS in addition to the other supported bits.
So I should do this:
SNDRV_PCM_RATES_5512 | SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_CONTINUOUS
That's not really elegant.
However, in your case these bits should be set according to the capabilities of the codec.
In the codec driver, I do that. With ASOC, each driver specifies its own capabilities, and ASOC is supposed to reconcile them. My I2S driver is not aware of the codec's capabilities.
Timur Tabi wrote:
Clemens Ladisch wrote:
To indicate that the PCM device supports all sample rates between the minimum and the maximum, set SNDRV_PCM_RATE_CONTINUOUS in addition to the other supported bits.
So I should do this:
SNDRV_PCM_RATES_5512 | SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_CONTINUOUS
Yes.
That's not really elegant.
How could this be made more elegant?
It would be possible for ALSA to automatically set the single rate bits that fall into the minimum/maximum range when the CONTINUOUS bit is set, but this wouldn't help in your case because you'd still need to set these bits in case one of the I2S/codec drivers has to remove the CONTINUOUS bit.
Regards, Clemens
Clemens Ladisch wrote:
So I should do this:
SNDRV_PCM_RATES_5512 | SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_CONTINUOUS
Yes.
That's not really elegant.
How could this be made more elegant?
Well, you could add SNDRV_PCM_RATE_ALL which be the sum of all SNDRV_PCM_RATE_xxx macros, where xxx is some number. So for today, that would be something like this:
#define SNDRV_PCM_RATE_ALL (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512)
At Tue, 24 Jul 2007 09:54:24 -0500, Timur Tabi wrote:
Clemens Ladisch wrote:
So I should do this:
SNDRV_PCM_RATES_5512 | SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_CONTINUOUS
Yes.
That's not really elegant.
How could this be made more elegant?
Well, you could add SNDRV_PCM_RATE_ALL which be the sum of all SNDRV_PCM_RATE_xxx macros, where xxx is some number. So for today, that would be something like this:
#define SNDRV_PCM_RATE_ALL (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512)
I'd prefer 5512_19200. The word "ALL" may vary in future.
Anyway, the bits SND_PCM_RATES_[0-9]* are ignored when _CONTINUOUS or _KNOT is passed. Only the values in rate_min/rate_max fields are referred as actual min/max rates.
Takashi
Takashi Iwai wrote:
#define SNDRV_PCM_RATE_ALL (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512)
I'd prefer 5512_19200. The word "ALL" may vary in future.
That's the point. It's supposed to indicate all sample rates no matter what they are or will be. However, that may be a moot point ...
Anyway, the bits SND_PCM_RATES_[0-9]* are ignored when _CONTINUOUS or _KNOT is passed. Only the values in rate_min/rate_max fields are referred as actual min/max rates.
Ah! I wish this stuff were documented in the source files.
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
At Tue, 24 Jul 2007 14:30:29 -0500, Timur Tabi wrote:
Takashi Iwai wrote:
#define SNDRV_PCM_RATE_ALL (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512)
I'd prefer 5512_19200. The word "ALL" may vary in future.
That's the point. It's supposed to indicate all sample rates no matter what they are or will be. However, that may be a moot point ...
Anyway, the bits SND_PCM_RATES_[0-9]* are ignored when _CONTINUOUS or _KNOT is passed. Only the values in rate_min/rate_max fields are referred as actual min/max rates.
Ah! I wish this stuff were documented in the source files.
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
In theory, yes, but these rate_min and rate_max are nothing but confusing in practice. Your hardware won't support definitely such rates, but the application can't know. Set some reasonable values there.
Takashi
Takashi Iwai wrote:
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
In theory, yes, but these rate_min and rate_max are nothing but confusing in practice. Your hardware won't support definitely such rates, but the application can't know. Set some reasonable values there.
This is an ASOC driver. My understanding is that ASOC will take all the values from the machine, PCM, I2S, and codec drivers and create the subset that matches all drivers. That's the point I was trying to make: my PCM driver does *not* decide what the capabilities of the system are, because my DMA controller can handle all speeds. So I don't want to put some arbitrary limits in the PCM driver, and then perhaps one day it gets attached to a codec driver that can handle 4000Hz, but ASOC won't allow it because I used SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512 in my PCM driver. ASOC would incorrectly believe that the PCM driver can't handle 4000Hz.
At Wed, 25 Jul 2007 09:37:34 -0500, Timur Tabi wrote:
Takashi Iwai wrote:
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
In theory, yes, but these rate_min and rate_max are nothing but confusing in practice. Your hardware won't support definitely such rates, but the application can't know. Set some reasonable values there.
This is an ASOC driver. My understanding is that ASOC will take all the values from the machine, PCM, I2S, and codec drivers and create the subset that matches all drivers. That's the point I was trying to make: my PCM driver does *not* decide what the capabilities of the system are, because my DMA controller can handle all speeds. So I don't want to put some arbitrary limits in the PCM driver, and then perhaps one day it gets attached to a codec driver that can handle 4000Hz, but ASOC won't allow it because I used SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512 in my PCM driver. ASOC would incorrectly believe that the PCM driver can't handle 4000Hz.
Then, rates = -1U, rate_min = 0, rate_max = -1U, are the correct values.
Takashi
At Wed, 25 Jul 2007 17:08:41 +0200, I wrote:
At Wed, 25 Jul 2007 09:37:34 -0500, Timur Tabi wrote:
Takashi Iwai wrote:
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
In theory, yes, but these rate_min and rate_max are nothing but confusing in practice. Your hardware won't support definitely such rates, but the application can't know. Set some reasonable values there.
This is an ASOC driver. My understanding is that ASOC will take all the values from the machine, PCM, I2S, and codec drivers and create the subset that matches all drivers. That's the point I was trying to make: my PCM driver does *not* decide what the capabilities of the system are, because my DMA controller can handle all speeds. So I don't want to put some arbitrary limits in the PCM driver, and then perhaps one day it gets attached to a codec driver that can handle 4000Hz, but ASOC won't allow it because I used SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512 in my PCM driver. ASOC would incorrectly believe that the PCM driver can't handle 4000Hz.
Then, rates = -1U, rate_min = 0, rate_max = -1U, are the correct values.
... of course, this assumes that codec and platform have the sane rate setting. ASoC should do some sanity checks...
Takashi
On Wed, 2007-07-25 at 17:12 +0200, Takashi Iwai wrote:
At Wed, 25 Jul 2007 17:08:41 +0200, I wrote:
At Wed, 25 Jul 2007 09:37:34 -0500, Timur Tabi wrote:
Takashi Iwai wrote:
So can I do this?
static const struct snd_pcm_hardware mpc86xx_pcm_hardware = {
.rates = SNDRV_PCM_RATE_CONTINUOUS, .rate_min = 1, .rate_max = (unsigned int) -1,
In theory, yes, but these rate_min and rate_max are nothing but confusing in practice. Your hardware won't support definitely such rates, but the application can't know. Set some reasonable values there.
This is an ASOC driver. My understanding is that ASOC will take all the values from the machine, PCM, I2S, and codec drivers and create the subset that matches all drivers. That's the point I was trying to make: my PCM driver does *not* decide what the capabilities of the system are, because my DMA controller can handle all speeds. So I don't want to put some arbitrary limits in the PCM driver, and then perhaps one day it gets attached to a codec driver that can handle 4000Hz, but ASOC won't allow it because I used SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATES_5512 in my PCM driver. ASOC would incorrectly believe that the PCM driver can't handle 4000Hz.
Then, rates = -1U, rate_min = 0, rate_max = -1U, are the correct values.
... of course, this assumes that codec and platform have the sane rate setting. ASoC should do some sanity checks...
Ok, I've marked this on my todo list ;)
Liam
participants (4)
-
Clemens Ladisch
-
Liam Girdwood
-
Takashi Iwai
-
Timur Tabi