Skip to content

[FEATURE] UCM: method to provide initial default mixer values #2067

Closed

Description

@kv2019i

There is currently no clear method for ALSA cards to express sensible defaults values to use via UCM files. The audio servers (like Pulseaudio) will typically maintain their own database of volume settings, so resetting the values each time a PCM is enabled, is not a good solution. But there is no explicit mechanism for e.g. Pulseaudio to ask the initial defaults when it is initializing the volume database for the first time.

Potential uses:

  • set suitable default gain for digital mics
  • set playback gains

Existing methods:

  • set default in UCM enable sequences (UCM files)
  • set defaults in /usr/share/alsa/init (alsa-utils package)

References:

FYI list @juimonen @libinyang @juimonen

Activity

  1. kv2019i commented on May 11, 2020

    @kv2019i
    CollaboratorAuthor

    One related issue: setting PGA volume values in EnableSequence thesofproject/alsa-ucm-conf#39

  2. juimonen commented on May 13, 2020

    @juimonen

    @perexg any comments for this? FYI also @tanuk, I understood pulseaudio doesn't have currently mechanism to read something like "first boot" values from UCM...

  3. perexg commented on May 13, 2020

    @perexg

    I would prefer to follow the global method to handle those values. I mean, set once then leave other applications like pulseaudio to modify the value per user requests.

    The current /usr/share/alsa/init database was designed for the drivers which creates the a few understandable controls. For ASoC, the control names are wild, but nothing prevents to add the new configs...

    We probably all agree that it will make sense to store the hardware settings and mapping at one place. For UCM, it will mean to find a way to describe the "boot" settings. The question is if we can resolve this with the current UCM schema or we should create some additions.

    From the first glance, I would run the global UCM enable block "SectionDefaults {}" only once at boot when the ALSA state file does not exist (see man alsactl). Or we can add new "SectionOnce {}". In other words, I believe that alsactl init command should care about the default volume settings.

  4. libinyang commented on May 14, 2020

    @libinyang

    @perexg @kv2019i I'm not sure if I understand Kai's idea correctly or not. I think Kai is talking about whether we can only set the kcontrols at the first time the system boots (the setting doesn't take effects at the second bootup) as there is no any setting to restore. After that, when system boots up, there is setting to restore (for example, /var/lib/alsa/asound.state for alsactl), so we don't need to setup the kcontrols in pulseaudio.
    Mostly, I think this is a good idea. I just have one concern that in case someone changes the alsamixer setting by fault. For example, he mutes some values. Then pulseaudio don't have chance to unmute it, which will cause the user can't change the setting in sound-setting?
    I tried SectionDefaults just now. Even there is alsa state file (/var/lib/alsa/asound.state), the setting in SectionDefaults will also be run when system boots up.

  5. perexg commented on May 14, 2020

    @perexg

    I just have one concern that in case someone changes the alsamixer setting by fault. Then pulseaudio don't have chance to unmute it, which will cause the user can't change the setting in sound-setting?

    I believe that it's the correct behaviour. The user may call alsactl init to restore the default values back. The alsactl restore is called for the normal system boot which will use the stored values from /var/lib/alsa/asound.state (if exists, otherwise the alsactl init is executed).

    I tried SectionDefaults just now. Even there is alsa state file (/var/lib/alsa/asound.state), the setting in SectionDefaults will also be run when system boots up.

    Actually, the SectionDefauls is used when pulseaudio boots up all time. I propose to use this only via alsactl at the system boot time when /var/lib/alsa/asound.state does not exist.

    Perhaps, we can really add new section SectionOnce for this purpose and keep SectionDefaults which is executed all time when UCM is activated. It's a bit different scheme.

  6. kv2019i commented on May 14, 2020

    @kv2019i
    CollaboratorAuthor

    Ack on above comments @perexg . So it seems "alsactl init" is really the intended mechanism to set the firstboot defaults. Thinking aloud, pros/cons I can see:

    • deployment speed -> alsactl init wins with faster deployment
      - pulseaudio already supports this -- with SectionOnce, upgrade cycle of pulseaudio would be needed to deploy this (in addition to card-specific data)
    • driver maintenance -> alsactl approach is more complex
      - for each new card/driver, developer needs to add UCM, alsa init defaults (and topology and FW in case of ASoC/SOF)
      - alsa-init rules are in alsa-utils repo
      - UCM files are in alsa-ucm repo
      - risk of users mixing versions of old/new UCM and alsa-utils
    • different lookup methods, duplicated rules -> having two systems is a problem as such
      - UCM uses cardname (and DMI) to find rules for a specific card
      - alsactl init uses different method for matching (PCI IDs, card names)

    I haven't written anything more complex in alsactl language, but it seems it is possible to express conditional rules, so the feature set is pretty close to UCM2 with conditionals.

    It would seem "alsactl" would be the faster method to deploy and main risk is the overhead of developers to manage high-level card-specific mixer rules in two places (and two languages). OTOH, both systems have been in place for a long time, so it's not like we can stop using one of them.

  7. perexg commented on May 14, 2020

    @perexg

    I will add SectionOnce to alsa-lib ASAP and improve alsactl to support this method of initialization (via UCM configs).

  8. perexg commented on May 14, 2020

    @perexg

    It's implemented now (latest alsa-lib and alsa-utils):

  9. kv2019i commented on May 14, 2020

    @kv2019i
    CollaboratorAuthor

    Thanks @perexg , wow, that was fast! @libinyang Could you give this a test run and use these to implement first-boot defaults (express the defaults in UCM via "_once")?

  10. kv2019i commented on May 14, 2020

    @kv2019i
    CollaboratorAuthor

    FYI @singalsu See above, this could be now used to set appropriate default gains for dmic.

  11. libinyang commented on May 15, 2020

    @libinyang

    otherwise the alsactl init is executed

    @perexg @kv2019i How will PulseAudio or sound-settings GUI call this new API alsactl init?

    Perhaps, we can really add new section SectionOnce for this purpose and keep SectionDefaults which is executed all time when UCM is activated. It's a bit different scheme.

    Yes, I think this SectionOnce is helpful. And my suggestion of its usage is:

    1. pulseaudio save its own setting, when pulseaudio found if its setting doesn't exist, it means this is the first time boot up. It will call SectionOnce. Otherwise it will skip it. Or pulseaudio can check /var/lib/alsa/asound.state existence to determine whether to load SectionOnce.
    2. GUI should allow user to load the SectionOnce manually in case some unknown issues cause alsamixer setting wrong. As the alsactl resotre always restore the previous setting, this means the wrong setting will always be restored. In this case, user can reset the setting to correct one.
  12. libinyang commented on May 18, 2020

    @libinyang

    @perexg @kv2019i I have tried the patch
    alsa-project/alsa-lib@a570634
    alsa-project/alsa-utils@4bea8fe
    And modify the UCM add

    SectionOnce {
        cset ....
    }
    

    After that, I run alsactl init. I found the cset in SectionOnce doesn't work.
    Is there anything wrong in my operation?

  13. perexg commented on May 18, 2020

    @perexg

    The syntax for SectionDefaults and SectionOnce is:

    SectionOnce [
      cset ....
    ]
    
  14. perexg commented on May 18, 2020

    @perexg

    otherwise the alsactl init is executed

    @perexg @kv2019i How will PulseAudio or sound-settings GUI call this new API alsactl init?

    PA should not call this. It's the system wide initialization. If everything works correctly, the systemd will execute this sequence once. If something is wrong, the user should run alsactl init from the command line which will execute those commands.

    EDIT: Related systemd services:

    https://github.com/alsa-project/alsa-utils/blob/master/alsactl/alsa-restore.service.in
    https://github.com/alsa-project/alsa-utils/blob/master/alsactl/alsa-state.service.in

  15. libinyang commented on May 19, 2020

    @libinyang

    @perexg Right, it works now. Maybe you would like to change the comments in parser.c for the usage of SectionOnce.

    the user should run alsactl init from the command line

    Do you think we need offer a GUI interface to do the 'alsactl init' in the future? The end user may not know this command.

  16. kv2019i commented on May 19, 2020

    @kv2019i
    CollaboratorAuthor

    @libinyang wrote:

    Do you think we need offer a GUI interface to do the 'alsactl init' in the future? The end user may not know this command.

    I think this goes out-of-scope for this PR and is a more complicated question. I mean the SectionOnce was a clear gap -- we needed a mechanism for different drivers to express defaults in a scalable manner and that is now covered. This is a capability which all distributions will want to have, irrespectively of the UI/desktop used.

    Resetting settings from sound UI, now that is not necessarily something all desktop UIs want to even expose to end users -- the prevailing trend is to keep even the settings UIs simple as possible. It is also more complicated to implement than just doing "alsactl init" as you would need to also reset the Pulseaudio internal database. A naive implementation would be to stop pulseaudio, clear pulseaudio database, run "alsactl init", restart Pulseaudio and let it populate the database.

  17. perexg commented on May 19, 2020

    @perexg

    @perexg Right, it works now. Maybe you would like to change the comments in parser.c for the usage of SectionOnce.

    Fixed. Thanks for the pointer.

  18. libinyang commented on May 20, 2020

    @libinyang
  19. perexg commented on May 25, 2020

    @perexg

    I am sorry for the confusion, but I renamed SectionOnce to more understandable BootSequence in the latest alsa-lib code. We have already EnableSequence and DisableSequence blocks with the same contents (commands), thus it makes sense to continue with this naming. Again, I am sorry for the confusion.

  20. plbossart commented on Jun 9, 2020

    @plbossart
    Member

    @perexg can you clarify one doubt I have: when would the BootSequence be executed? It's not usual for a lot of tests to use a "blacklist snd-sof-pci" and manually do a "modprobe snd-sof-pci". This helps track issues that are difficult to see if the boot is stuck. we also have quite a few tests where we load/unload modules on purpose to look for initialization problems?
    I understand that systemd would run this BootSequence once, but when? On card creation? If yes, what's the difference with the Defaults? if no, does this mean our tests will give different results if run with the driver probe at boot or after a manual modprobe.

    For the end-user it doesn't matter but for test/development it does.

  21. plbossart commented on Jun 10, 2021

    @plbossart
    Member

    I think this enhancement is implemented now, should we close it @libinyang @kv2019i ?

  22. kv2019i commented on Jun 11, 2021

    @kv2019i
    CollaboratorAuthor

    Ack, this is done, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions