takaswie / linux-firewire-dkms

Currently this repository is maintained for Linux firewire subsystem and unit drivers.
http://ieee1394.docs.kernel.org/
40 stars 8 forks source link

saf pro40 - cannot get alsa / lib spa / pipewire to see / recognise 96khz mode (it still sees 48000 max) #54

Open dreamcat4 opened 11 months ago

dreamcat4 commented 11 months ago

Link to Log excerpts: https://gist.github.com/dreamcat4/42260017a29eb7c718c10bbaec60f69b

Hi @takaswie, Very pleased to see how good is firewire alsa device controls. Now that they are integrated into latest kernel. (and am running 6.5 / 6.6 here)...

Most things works pretty well and with sudo alsactl store to save the state (between reboots).

So 1st set my saffire pro 40 interface into 96khz mode:

# 1. use cget / cset to set hardware config = '3' == 96khz
$ amixer -c0 cget iface=CARD,name=clock-rate
numid=11,iface=CARD,name='clock-rate'
  ; type=ENUMERATED,access=rw----W-,values=1,items=4
  ; Item #0 '44100'
  ; Item #1 '48000'
  ; Item #2 '88200'
  ; Item #3 '96000'
  : values=3

# 2. remove any old (or broken) alsa settings
$ sudo rm /var/lib/alsa/asound.state

# 3. persist card settings across restarts
$ sudo alsactl store

Unfortunately when pipewire daemon starts, it goes through all of it's plugins stack loading and probing to alsa. With Tim's libspa ? Or what is the alsa apis. And then inside of pipewire, the object properties onto any hardware streams still maxes out to only the default 48khz. So the hardware alsa setting rate up to 96k does not get noticed? Or perhaps (if not a bug or other problem)... then there is some other tricks needed for this?

Here we can see in the pw-dump the object properties onto the hardware's node objects PipeWire:Interface:Node, we can see here:

    "params": {
      "EnumFormat": [
        {
          "mediaType": "audio",
          "mediaSubtype": "raw",
          "format": "S32LE",
          "rate": {
            "default": 48000,
            "min": 44100,
            "max": 48000
          },

Link: https://gist.github.com/dreamcat4/42260017a29eb7c718c10bbaec60f69b#file-pw-dump-card-0-after-cset-rate3-96000-json-L1832-L1842

And of course, that the reported "max" rate is 48000 --> pipewire plays the streams at 48k

Link: https://gist.github.com/dreamcat4/42260017a29eb7c718c10bbaec60f69b#file-pw-top-c-L7

So looking into the alsa kernel sources, I can indeed see that for snd_dice kernel module... we have those different modes depending upon the hardware etc... that is the array of snd_dice_rates

Link: https://gist.github.com/dreamcat4/42260017a29eb7c718c10bbaec60f69b#file-snd_dice-alsa-kernel-module-reference-c

However when i query the kernel module, there is not any kernel params to set (no options) to configure the modes, for to try and force the rates.

So I was wondering @takaswie what can I try next about forcing the 96khz rate? For example, should I try to force pipewire to override the pipewire properties? And then see what might happen.

Or is there some other hardware setting / modes to configure in the alsa hardware interface... some more cset commands to bring the hardware into 96khz mode setting?

dreamcat4 commented 11 months ago

Also: much love my friend 💙

takaswie commented 10 months ago

Hi,

Sorry to be late, but I'm working for AMD Ryzen issue to use ASM1083/VT6306 PCI card.

I think your Focusrite Saffire Pro 40 is the one with TCD2220, not [with TCD3070](https://lore.kernel.org/alsa devel/20221130143313.43880-1-o-takashi@sakamocchi.jp/). In both cases, ALSA dice driver has no restriction about sampling rate, thus it is possible to use 96.0 kHz PCM substreams.

I'm not so good at PipeWire configuration, however I think the point is ALSA dice driver adds four PCM character devices in the case and the character devices affects each other for sampling rate (and the number of channels).

$ pw-top.c 
...
S  121      0      0    ---     ---   ---   ---     0                  alsa_output.firewire-0x00130e040140822d.pro-output-0
S  122      0      0    ---     ---   ---   ---     0                  alsa_output.firewire-0x00130e040140822d.pro-output-1
S  123      0      0    ---     ---   ---   ---     0                  alsa_input.firewire-0x00130e040140822d.pro-input-0
S  124      0      0    ---     ---   ---   ---     0                  alsa_input.firewire-0x00130e040140822d.pro-input-1
...

If one of the character device is opened and configured at 48.0 kHz, the hardware is configured to 48.0 kHz mode, then the rest of character devices get the restriction as long as the first character device is used for packet streaming.

The configuration for all of the character devices would resolve the issue, in my opinion.

dreamcat4 commented 10 months ago

thanks @takaswie!

your Focusrite Saffire Pro 40 is the one with TCD2220,

yes correct. sorry for not clarifying but this is indeed the original saffire pro 40 hardware with the older dice 2000 series chip. the 1st hardware version...

note: btw in my gist log (pw-top) the 4 lines ... 121-124 is actually my 2nd hardware interface (with different fw mac address). that was never used for this rates tests. so those lines / other hardware just plugged in. but its remained totally inactive, to ignore.

now about the way the rate gets set. indeed it requires some further investigations (and also on my side here). perhaps to also consult with the pipewire team.

for example: i since tried adding a wireplumber rule to rewrite the properties onto the node object. however (wireplumber as a 3rd party service gets launched after pipewire)... that rule is only applied after pipewire has already created the playback node / stream object. and started the playback. at which time (after the stream playback has started). then it seems to be already too late. and the node properties values remains at the same orginal 48000.

other previous debugging attempts:

it was earlier this year, tried to debug the pipewire plugin loading chains. using vscode / gdb. and pipewire daemon has this complex loop to load its plugins (based on config file). as an array loop in c. it enters / exits some many levels of stack. and that 1 of the plugins then is the libspa for alsa drivers. which then loads the hardware (the soundcard).

however that debugging session was too complex to hit so many watch points. to then stop onto the libspa plugin loading. due to the generic and modular ways the pipewire gets configured and loaded. a very complex chain of events driven sequence.

but at the heart of it, there is indeed a libspa c apis. and some defaults or fallback assumptions in regards to hardware rates detection within pipewire. perhaps incomplete of missing somewhere.

for example: if the alsa driver does not set or report / return any specific rates. then perhaps pipewire daemon is choosing something as a default 48000 safe rate. that is because it is assumed when the hardware cannot be known. or incomplete probing / not probed fully. this was the point i had previously discussed with @wtaymans (it was many months ago)... which makes some sense. but it was not quite specific enough to discover exactly the right code locations. for where it's happening.

because if i remember correct, i had then tried during those debugging effort. to be searching pipewire source code and trying to speculatively hardcode 96000 into those c variables (then recompile in git repo / vscode). and run in gdb. but no luck. it was then abandoned effort after being unable to watchpoint and stop in gdb onto the libspa module. to then see the actual point where the hardware is detected (in pipewire) that this rate setting is assumed to occur.

however the more recent observation is that no fixed rate is actually being set or chosen (or maybe even probed?) at that initial daemon startup time in pipewire either! if not happened during the daemon start. just the hardware interfacee's other more general properties is being loaded up. which of course we do see in the pipewire some of the properties. in pipewire the object of the alsa hardware itself (of the saffire pro 40 device). however it does not show any list of known available rates in its general hardware object properties. there is not a rates entry for that type of object, which is of type PipeWire:Interface:Device. it instead gives the plugin, the driver (alsa spa). and then the alsa card profile.

instead the rates (in pipewire's object properties). only is ever seen applied onto an actual stream object. which occurs when opening a stream to connect to the hardware. with another active node to supply or to consume an open stream. at this point is when the hardware node object is for the other type PipeWire:Interface:Node.

so perhaps i was looking in the wrong places all along previously. and need to rethink how to find it. or to learn more about how streams are being created and negotiated before being opened in the libspa alsa apis. or in the pipewire modules (that then talks to the libspa). so it could be well after the daemon startup loading. perhaps... not sure yet!

so perhaps can return back to this matter later on. or that i can look in other runtime places. for where this is actually happening. for the hardware rates setting.

dreamcat4 commented 10 months ago

my alsa config...

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf

Highlighted parts:

cards.0 'cards.DICE'
cards.2 'cards.HDA-Intel'

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf-L1083

cards.4 'cards.HDA-Intel'
cards.5 'cards.USB-Audio'
cards.6 'cards.DICE'
defaults.namehint.showall on
defaults.namehint.basic on

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf-L2404

defaults.pcm.dmix.rate 48000

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf-L2421

defaults.pipewire.rate 0

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf-L2476

pcm.samplerate.RATE.default 96000

but:

pcm.speexrate.RATE.default 48000
(however speex seems to be just some resampler plugin, which isn't being used)

https://gist.github.com/dreamcat4/747767b705ee77ee987e3399d77f3513#file-alsactl-dump-config-conf-L2712-L2752