Re: [alsa-devel] ASoC:Question rate constraint between the dais
I need to make sure that all simultaneous playback and capture (across the all dai_links) needs to be of same frequency family. If the sampling frequency of a new request is different from ongoing playback/capture, then it needs to be rejected.
How do I handle it in machine driver?
Why do you need to do this in the machine driver? Such a constraint sounds like it's coming from one of the chips in the system rather than from the machine itself so it'd seem sensible for the chip itself to impose the constraint so that other machines don't need to replicate the code.
See wm8988 for an example of adding sample rate constraints, obviously you can change the criteria dynamically.
You are right to say that it is not a machine constraint but a codec constraint. The problem is that if a DAI (say the "SN95031 Headset DAI") is opened with a 44.1 khz rate, then another DAI (say "SN95031 Voice") is opened with a 48 khz rate, then we need to reject the second open because the codec cannot support both rates at the same time.
Is there any way to do this with constraint_lists? The way it is done in the wm8988 driver does not apply here because there it is a single DAI.
On Fri, Mar 16, 2012 at 03:35:18PM +0530, Omair Mohammed Abdullah wrote:
You are right to say that it is not a machine constraint but a codec constraint. The problem is that if a DAI (say the "SN95031 Headset DAI") is opened with a 44.1 khz rate, then another DAI (say "SN95031 Voice") is opened with a 48 khz rate, then we need to reject the second open because the codec cannot support both rates at the same time.
Is there any way to do this with constraint_lists? The way it is done in the wm8988 driver does not apply here because there it is a single DAI.
There's a way to do this, and it's the way that the WM8988 driver is doing it - obviously you'll have different criteria for choosing constraints but the actual application of the constraints is going to be done in the same way.
On Fri, Mar 16, 2012 at 3:22 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Fri, Mar 16, 2012 at 03:35:18PM +0530, Omair Mohammed Abdullah wrote:
You are right to say that it is not a machine constraint but a codec constraint. The problem is that if a DAI (say the "SN95031 Headset DAI") is opened with a 44.1 khz rate, then another DAI (say "SN95031 Voice") is opened with a 48 khz rate, then we need to reject the second open because the codec cannot support both rates at the same time.
Is there any way to do this with constraint_lists? The way it is done in the wm8988 driver does not apply here because there it is a single DAI.
There's a way to do this, and it's the way that the WM8988 driver is doing it - obviously you'll have different criteria for choosing constraints but the actual application of the constraints is going to be done in the same way.
Since the constraint is based on the current configuration of another DAI, the two DAIs need some way to query each other's parameters. The fsl_ssi driver is a better example for that, as it has a constraint like this that is dynamic and based on the current configuration of another substream.
And as I said before, ALSA doesn't handle this 100%. There is a race if both streams are initialized at the same time. If you open one stream, setup the parameters, then open another stream, the second stream opened will have the proper constraints. But if you open the second stream _before_ the first has setup it's parameters (called ->hw_params() method) then the second won't have the proper constraints. How can the 2nd stream constrain the rate to that of the 1st stream when the 1st has yet to choose a rate?
I think what's necessary is for ALSA to let hw_params return an error code that means lets the driver say, "Sorry, the constraints have changed and the hw_params you have chosen are no longer valid. Here are new constraints, please try again."
And in turn you need ALSA lib and application code to be able to handle a sequence like this: "We have 44.1k and 48k rates available." "I'd like 48k." "I'm sorry, we're out of 48k, would you like 44.1k?"
On Fri, Mar 16, 2012 at 06:01:44PM -0400, Trent Piepho wrote:
On Fri, Mar 16, 2012 at 3:22 PM, Mark Brown
There's a way to do this, and it's the way that the WM8988 driver is doing it - obviously you'll have different criteria for choosing constraints but the actual application of the constraints is going to be done in the same way.
Since the constraint is based on the current configuration of another DAI, the two DAIs need some way to query each other's parameters. The
Since they're both provided by the same driver this is trivial.
And as I said before, ALSA doesn't handle this 100%. There is a race if both streams are initialized at the same time. If you open one
Yes, I did reply to your previous mail about that pointing out that this is impossible...
I think what's necessary is for ALSA to let hw_params return an error code that means lets the driver say, "Sorry, the constraints have changed and the hw_params you have chosen are no longer valid. Here are new constraints, please try again."
Thinking about this slightly further than in my reply to Lars-Peter a few minutes ago...
I think just returning -EINVAL on bad parameters (which is pretty much what we do) is sufficient for this if the driver is good about keeping the constraints up to date. Applications should already be able to take the hint, though I imagine most of them wouldn't trust the drivers to provide accurate constraints and aren't as widely deployed as PulseAudio (which forced fixing the DMA stuff by virtue of everyone using it). Though just spinning a small number of times will probably deal with lying drivers well enough.
We could still generate an event but I'm now even less sure it's worth drivers doing anything special about this.
On Sat, Mar 17, 2012 at 7:48 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Fri, Mar 16, 2012 at 06:01:44PM -0400, Trent Piepho wrote:
On Fri, Mar 16, 2012 at 3:22 PM, Mark Brown
There's a way to do this, and it's the way that the WM8988 driver is doing it - obviously you'll have different criteria for choosing constraints but the actual application of the constraints is going to be done in the same way.
Since the constraint is based on the current configuration of another DAI, the two DAIs need some way to query each other's parameters. The
Since they're both provided by the same driver this is trivial.
It's not that trivial with the sub-streams in question aren't in the same instance of the driver, e.g. playback and record. Say you had two WM8988 codecs, how does one codec get a handle to the other? There's no global list of codecs in the driver, so you have to add something like that. Or change the device tree binding to give the slave codec a phandle to the master codec.
And as I said before, ALSA doesn't handle this 100%. There is a race if both streams are initialized at the same time. If you open one
Yes, I did reply to your previous mail about that pointing out that this is impossible...
...which didn't arrive until after I started writing my email.
I think what's necessary is for ALSA to let hw_params return an error code that means lets the driver say, "Sorry, the constraints have changed and the hw_params you have chosen are no longer valid. Here are new constraints, please try again."
Thinking about this slightly further than in my reply to Lars-Peter a few minutes ago...
I think just returning -EINVAL on bad parameters (which is pretty much what we do) is sufficient for this if the driver is good about keeping the constraints up to date. Applications should already be able to take the hint, though I imagine most of them wouldn't trust the drivers to provide accurate constraints and aren't as widely deployed as PulseAudio (which forced fixing the DMA stuff by virtue of everyone using it). Though just spinning a small number of times will probably deal with lying drivers well enough.
Does PulseAudio handle it if hw_params fails? From what I've seen, most applications just fail if hw_params fails.
I think there is still a race in the design of ALSA, in that the driver checking the parameters in its hw_params() method is not atomic with the substream being assigned those parameters, w.r.t. another substream.
The problem is in the code for snd_pcm_hw_params(),
405 err = snd_pcm_hw_params_choose(substream, params); 406 if (err < 0) 407 goto _error; 408 409 if (substream->ops->hw_params != NULL) { 410 err = substream->ops->hw_params(substream, params); 411 if (err < 0) 412 goto _error; 413 } 414 415 runtime->access = params_access(params); ... 455 runtime->status->state = SNDRV_PCM_STATE_SETUP;
At line 410 the driver is given a chance to approve the selected hw_params. It can look at any of the joint substreams, and if they are in state >= SETUP, verify that the hw_params are still valid and if not, update the constraints and return an error. But it is not until line 455 that the substream has actually finished getting the parameters and entered the SETUP state. There is no lock to prevent another substream from entering this code at the same time. To fix the race, there would need to be a critical section from line 408-455 that only one substream of the group with joint constraints can enter at one time.
On Sat, Mar 17, 2012 at 03:49:06PM -0400, Trent Piepho wrote:
On Sat, Mar 17, 2012 at 7:48 AM, Mark Brown
On Fri, Mar 16, 2012 at 06:01:44PM -0400, Trent Piepho wrote:
Since the constraint is based on the current configuration of another DAI, the two DAIs need some way to query each other's parameters. The
Since they're both provided by the same driver this is trivial.
It's not that trivial with the sub-streams in question aren't in the same instance of the driver, e.g. playback and record. Say you had
It's very easy to go back from the DAI to the CODEC, there's a direct pointer.
two WM8988 codecs, how does one codec get a handle to the other?
Such a constraint would be machine imposed, not CODEC imposed - the case the Intel guys were talking about was a constraint between the two interfaces on a single CODEC. There's no way the driver for one CODEC should be doing anything about another CODEC.
There's no global list of codecs in the driver, so you have to add something like that. Or change the device tree binding to give the
You're talking about a totally different use case here, there's way more issues than just the constraints getting multiple CODECs on the same link to play nicely.
slave codec a phandle to the master codec.
No, that wouldn't be sensible - this should all be handled at the DAI level. Adding explicit code in individual CODEC drivers for this would be an awful lot of duplication.
Does PulseAudio handle it if hw_params fails? From what I've seen, most applications just fail if hw_params fails.
I've no idea what PulseAudio does; I suppose someone who's interested could look at the code. Most applications do just fail, like I say it's exceptionally rare to hit any of thist stuff.
are in state >= SETUP, verify that the hw_params are still valid and if not, update the constraints and return an error. But it is not until line 455 that the substream has actually finished getting the
So long as the driver takes care that only one of multiple concurrent hw_params() calls manages to successfully return we should be fine, once the hw_params() call has returned we're committed to flagging success.
On Sun, Mar 18, 2012 at 1:19 AM, Trent Piepho tpiepho@gmail.com wrote:
There's a way to do this, and it's the way that the WM8988 driver is doing it - obviously you'll have different criteria for choosing constraints but the actual application of the constraints is going to be done in the same way.
Since the constraint is based on the current configuration of another DAI, the two DAIs need some way to query each other's parameters. The
Since they're both provided by the same driver this is trivial.
It's not that trivial with the sub-streams in question aren't in the same instance of the driver, e.g. playback and record. Say you had two WM8988 codecs, how does one codec get a handle to the other?
A CODEC is constrained only by its own, not by its another instance. If your machine routes related signals to two instances of the CODEC, then you have constraints at machine level, still not at codec level. So your machine driver should keep track of the first active codec's configuration and impose that on dais of the other as requests come. If actually your machine doesn't impose any such constraint, it becomes a policy, which should be imposed from user-space.
Implementation wise, maybe two tightly coupled dais at machine level, could be represented as one virtual dai with independent virtual 'mute' switches for each physical path?
I find it so obvious, so perhaps I am overlooking something :D
-j
On Sun, Mar 18, 2012 at 11:52:01AM +0530, Jassi Brar wrote:
Implementation wise, maybe two tightly coupled dais at machine level, could be represented as one virtual dai with independent virtual 'mute' switches for each physical path?
When I've considered implementing this in the past I've thought about doing something like having DAI groups which own the physical link configuration when you've got more than one logical link on the same physical infrastructure. The physical configuration would then get punted up to the group level and we'd need some mechanism for the group to start clocks when required.
I've only ever thought about it though so there may be some problems there I've not come up with yet. Might be useful to start the refactoring for the clocks anyway, might be useful for the reconfigurable channel allocation cases too.
participants (4)
-
Jassi Brar
-
Mark Brown
-
Omair Mohammed Abdullah
-
Trent Piepho