Disable optical sound line on MacBook Pros

Each time I booted in openSUSE, the digital optical line was activated (output of red light from the mini jack port), so after some google searchs, I’ve found how to disable this with the help of ALSA:

  1. Fire up a root shell and launch alsamixer(1)
  2. Use the arrow keys to move around and when over S/PDIF press M to mute (if there’s more than one S/PDIF lines cycle mute through each of those until this turns off the light)
  3. Hit the Escape key - DO NOT CLOSE TERMINAL
  4. Type sudo alsactl store -f /var/lib/alsa/asound.state
  • This will make it persist across reboots 1. Close the shell

A minor remark/question.

Why do you use sudo in #4 when you already fired up a root shell in #1?

Nice catch! Thanks :wink:
Its a typo, call to sudo(8) isn’t needed :good:

Unfortunately, calling alsamixer(1) from a root shell or with sudo(8) doesn’t work anymore on openSUSE Tumbleweed (20201119 snapshot here) so as a workaround I’ve created the following .desktop file to autostart from your DE a call to alsactl(1):

alsactl --file ~/.config/asound.state store

Create with your favorite editor the alsarestore.desktop file:

vim ~/.config/autostart/alsarestore.desktop

with the following content:

[Desktop Entry]
Type=Application
Terminal=false
Name=alsarestore
Exec=bash -c 'sleep 15 ; alsactl --file ~/.config/asound.state restore'

Another cleaner way of disabling at boot the S/PDIF on MacBook Pros running Tumbleweed and globally is making systemd(1) handles this with a help of a new service and timer as by default alsa tries to restore /var/lib/alsa/asound.state before the sound card driver is entirely loaded by the kernel.

On a root shell:1. Create a new systemd service “/etc/systemd/system/alsa-restore-delayed.service” with the following content after disabling the S/PDIF output (see my first message of this tread):

[Unit]
Description=Delayed Restore Sound Card State 
ConditionPathExists=!/etc/alsa/state-daemon.conf
ConditionPathExistsGlob=/dev/snd/control*
ConditionPathExists=/var/lib/alsa/asound.state

[Service]
Type=oneshot
ExecStart=-/usr/sbin/alsactl restore
  1. Create a systemd timer “/etc/systemd/system/alsa-restore-delayed.timer” with the following content:
[Unit]
Description=Timer Delayed Restore Sound Card State

[Timer]
OnBootSec=30
  1. Add the timer at multi-user.target:
systemctl add-wants multi-user.target alsa-restore-delayed.timer && systemctl daemon-reload

Credits goes to user laurent85

openSUSE has its own alsa services:

**erlangen:~ #** systemctl list-unit-files 'alsa*'               
UNIT FILE            STATE  VENDOR PRESET 
alsa-restore.service static -             
alsa-state.service   static -             
alsasound.service    **alias  **-             

3 unit files listed. 
**erlangen:~ #**

openSUSE has target:

**erlangen:~ #** systemctl list-dependencies timers.target             
timers.target 
**●** ├─backup-home.timer 
**●** ├─backup-rpmdb.timer 
**●** ├─backup-sysconfig.timer 
**●** ├─btrfs-balance.timer 
**●** ├─btrfs-defrag.timer 
**●** ├─btrfs-scrub.timer 
**●** ├─btrfs-trim.timer 
**●** ├─fstrim.timer 
**●** ├─logrotate.timer 
**●** ├─mandb.timer 
**●** ├─mlocate.timer 
**●** ├─packagekit-background.timer 
**●** ├─snapper-cleanup.timer 
**●** ├─snapper-timeline.timer 
**●** └─systemd-tmpfiles-clean.timer 
**erlangen:~ #**

Timers have an install section:

[Install] 
WantedBy=timers.target

You may try to use vendor versions of alsa services.

Thanks for your inputs. However none of the default timer and systemd services bundled with Tumbleweed works with these laptops.
The S/PDIF is always active despite custom settings set with alsamixer(1) and saved on /var/lib/alsa/asound.state.

At first view, with none of the workarounds I’ve made, leaving Tumbleweed doing its stuff, /var/lib/alsa/asound.state is reseted at each boot no matter what custom settings are saved with alsactl store on /var/lib/alsa/asound.state.
From logs, this shows alsa is trying to apply settings before the sound card driver is fully loaded, thus overwriting custom /var/lib/alsa/asound.state with a new one.

With Leap 15.2, it just works whereas it’s not with Tumbleweed snapshots I’ve tested and actually use, so the last workaround I’ve posted actually works on all of the MacBook Pros I resurrected thanks to openSUSE :wink:

Thanks for the feedback! Are you sure:

**erlangen:~ #** journalctl -b -1 -u alsa-restore.service  
-- Logs begin at Sat 2020-11-14 06:05:06 CET, end at Thu 2020-11-26 18:44:19 CET. -- 
Nov 25 21:05:16 erlangen systemd[1]: Starting Save/Restore Sound Card State... 
Nov 25 21:05:17 erlangen systemd[1]: Finished Save/Restore Sound Card State. 
Nov 26 18:42:00 erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
Nov 26 18:42:00 erlangen systemd[1]: alsa-restore.service: Succeeded. 
Nov 26 18:42:00 erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
**erlangen:~ #** systemctl status alsa-restore.service 
**●** alsa-restore.service - Save/Restore Sound Card State 
     Loaded: loaded (/usr/lib/systemd/system/alsa-restore.service; static) 
     Active: **active (exited)** since Thu 2020-11-26 18:42:37 CET; 5min ago 
    Process: 763 ExecStart=/usr/sbin/alsactl restore (code=exited, status=0/SUCCESS) 
   Main PID: 763 (code=exited, status=0/SUCCESS) 

Nov 26 18:42:37 erlangen systemd[1]: Starting Save/Restore Sound Card State... 
Nov 26 18:42:37 erlangen systemd[1]: Finished Save/Restore Sound Card State. 
**erlangen:~ #**

Did you check conditions?

**erlangen:~ #** systemctl cat alsa-restore.service    
**# /usr/lib/systemd/system/alsa-restore.service**
# 
# Note that two different ALSA card state management schemes exist and they 
# can be switched using a file exist check - /etc/alsa/state-daemon.conf . 
# 

[Unit] 
Description=Save/Restore Sound Card State 
**ConditionPathExists=!/etc/alsa/state-daemon.conf 
ConditionPathExistsGlob=/dev/snd/control* 
ConditionPathExists=/var/lib/alsa/asound.state 
**
[Service] 
Type=oneshot 
RemainAfterExit=true 
ExecStart=-/usr/sbin/alsactl restore 
ExecStop=-/usr/sbin/alsactl store 
**erlangen:~ #**



You’re welcome :wink:
Yes (do note on the following output I have disabled alsa-restore.service but still having the same output if /etc/alsa/state-daemon.conf is there and this service is enabled):

**root@raiatea:/home/matt #** journalctl -b -1 -u alsa-restore.service 
-- Logs begin at Sun 2020-11-22 13:30:29 CET, end at Fri 2020-11-27 02:48:05 CET. --
nov. 26 15:46:14 raiatea systemd[1]: Starting Save/Restore Sound Card State...
nov. 26 15:46:14 raiatea systemd[1]: Finished Save/Restore Sound Card State.
nov. 27 02:10:49 raiatea.local systemd[1]: Stopping Save/Restore Sound Card State...
nov. 27 02:10:49 raiatea.local systemd[1]: alsa-restore.service: Succeeded.
nov. 27 02:10:49 raiatea.local systemd[1]: Stopped Save/Restore Sound Card State.
root@raiatea:/home/matt # systemctl status alsa-restore.service    
● alsa-restore.service - Save/Restore Sound Card State
     Loaded: loaded (/usr/lib/systemd/system/alsa-restore.service; static)
     Active: **inactive (dead)**
  Condition: start condition failed at Fri 2020-11-27 02:11:07 CET; 38min ago
             └─ **ConditionPathExistsGlob=/dev/snd/control* was not met**

nov. 27 02:11:07 raiatea systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped.
**root@raiatea:/home/matt # **


Also yes:

**root@raiatea:/home/matt #** systemctl cat alsa-restore.service
# /usr/lib/systemd/system/alsa-restore.service
#
# Note that two different ALSA card state management schemes exist and they
# can be switched using a file exist check - /etc/alsa/state-daemon.conf .
#

[Unit]
Description=Save/Restore Sound Card State
ConditionPathExists=!/etc/alsa/state-daemon.conf
ConditionPathExistsGlob=/dev/snd/control*
ConditionPathExists=/var/lib/alsa/asound.state

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=-/usr/sbin/alsactl restore
ExecStop=-/usr/sbin/alsactl store
**root@raiatea:/home/matt # **

Why one of alsa-restore.service’s condition is not met puzzle me and lead me to think that the sound card driver isn’t fully loaded before the service is run. On Leap 15.2 no such problem after muting the S/PDIF in alsamixer(1).

What are yours:

**erlangen:~ #** systemctl list-dependencies alsa-restore.service 
alsa-restore.service 
**●** ├─system.slice 
**●** └─sysinit.target 
**●**   ├─dev-hugepages.mount 
**●**   ├─dev-mqueue.mount 
**●**   ├─dracut-shutdown.service 
**●**   ├─haveged.service 
**●**   ├─kmod-static-nodes.service 
**●**   ├─plymouth-read-write.service 
**●**   ├─plymouth-start.service 
**●**   ├─proc-sys-fs-binfmt_misc.automount 
**●**   ├─sys-fs-fuse-connections.mount 
●   ├─sys-kernel-config.mount 
**●**   ├─sys-kernel-debug.mount 
**●**   ├─sys-kernel-tracing.mount 
●   ├─systemd-ask-password-console.path 
●   ├─systemd-binfmt.service 
●   ├─systemd-boot-system-token.service 
●   ├─systemd-firstboot.service 
●   ├─systemd-hwdb-update.service 
●   ├─systemd-journal-catalog-update.service 
**●**   ├─systemd-journal-flush.service 
**●**   ├─systemd-journald.service 
●   ├─systemd-machine-id-commit.service 
**●**   ├─systemd-modules-load.service 
**●**   ├─systemd-random-seed.service 
**●**   ├─systemd-sysctl.service 
●   ├─systemd-sysusers.service 
**●**   ├─systemd-tmpfiles-setup-dev.service 
**●**   ├─systemd-tmpfiles-setup.service 
**●**   ├─systemd-udev-trigger.service 
**●**   ├─systemd-udevd.service 
●   ├─systemd-update-done.service 
**●**   ├─systemd-update-utmp.service 
**●**   ├─cryptsetup.target 
**●**   ├─local-fs.target 
**●**   │ ├─-.mount 
**●**   │ ├─\x2esnapshots.mount 
**●**   │ ├─boot-efi.mount 
**●**   │ ├─boot-grub2-i386\x2dpc.mount 
**●**   │ ├─boot-grub2-x86_64\x2defi.mount 
**●**   │ ├─home.mount 
**●**   │ ├─home\x2dSSD.mount 
**●**   │ ├─opt.mount 
**●**   │ ├─root.mount 
**●**   │ ├─srv.mount 
**●**   │ ├─systemd-remount-fs.service 
**●**   │ ├─tmp.mount 
**●**   │ ├─usr-local.mount 
●   │ ├─var-lock.mount 
●   │ ├─var-run.mount 
**●**   │ └─var.mount 
**●**   └─swap.target 
**erlangen:~ #**


**root@raiatea:/home/matt # **systemctl list-dependencies alsa-restore.service
alsa-restore.service
● ├─system.slice
● └─sysinit.target
●   ├─dev-hugepages.mount
●   ├─dev-mqueue.mount
●   ├─dracut-shutdown.service
●   ├─haveged.service
●   ├─kmod-static-nodes.service
●   ├─plymouth-read-write.service
●   ├─plymouth-start.service
●   ├─proc-sys-fs-binfmt_misc.automount
●   ├─sys-fs-fuse-connections.mount
●   ├─sys-kernel-config.mount
●   ├─sys-kernel-debug.mount
●   ├─sys-kernel-tracing.mount
●   ├─systemd-ask-password-console.path
●   ├─systemd-binfmt.service
●   ├─systemd-boot-system-token.service
●   ├─systemd-firstboot.service
●   ├─systemd-hwdb-update.service
●   ├─systemd-journal-catalog-update.service
●   ├─systemd-journal-flush.service
●   ├─systemd-journald.service
●   ├─systemd-machine-id-commit.service
●   ├─systemd-modules-load.service
●   ├─systemd-random-seed.service
●   ├─systemd-sysctl.service
●   ├─systemd-sysusers.service
●   ├─systemd-tmpfiles-setup-dev.service
●   ├─systemd-tmpfiles-setup.service
●   ├─systemd-udev-trigger.service
●   ├─systemd-udevd.service
●   ├─systemd-update-done.service
●   ├─systemd-update-utmp.service
●   ├─cryptsetup.target
●   ├─local-fs.target
●   │ ├─-.mount
●   │ ├─\x2esnapshots.mount
●   │ ├─boot-efi.mount
●   │ ├─boot-grub2-i386\x2dpc.mount
●   │ ├─boot-grub2-x86_64\x2defi.mount
●   │ ├─home.mount
●   │ ├─opt.mount
●   │ ├─root.mount
●   │ ├─srv.mount
●   │ ├─systemd-remount-fs.service
●   │ ├─tmp.mount
●   │ ├─usr-local.mount
●   │ ├─var-lock.mount
●   │ ├─var-run.mount
●   │ └─var.mount
●   └─swap.target
●     └─dev-disk-by\x2duuid-debae52d\x2d668c\x2d4013\x2db283\x2dbcb6297fc762.swap


That looks the same as here. I remember that erlangen had some problems too:

    4.949788] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    5.051452] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.335229] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.293863] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.056816] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.334760] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.226093] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.343069] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    4.456605] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
    3.951069] erlangen systemd[1]: Condition check resulted in Save/Restore Sound Card State being skipped. 
 4414.243377] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
 4414.246647] erlangen alsactl[25044]: No state is present for card PCH 
 4414.246956] erlangen alsactl[25044]: alsa-lib main.c:1014:(snd_use_case_mgr_open) error: failed to import hw:0 use case configuration -2 
 4414.246956] erlangen alsactl[25044]: Found hardware: "HDA-Intel" "Realtek ALC892" "HDA:10ec0892,18495892,00100302" "0x1849" "0x5892" 
 4414.246956] erlangen alsactl[25044]: Hardware is initialized using a generic method 
 4414.247320] erlangen alsactl[25044]: No state is present for card PCH 
 4414.247375] erlangen alsactl[25044]: No state is present for card HDMI 
 4414.247487] erlangen alsactl[25044]: alsa-lib main.c:1014:(snd_use_case_mgr_open) error: failed to import hw:1 use case configuration -2 
 4414.247640] erlangen alsactl[25044]: Found hardware: "HDA-Intel" "ATI R6xx HDMI" "HDA:1002aa01,00aa0100,00100700" "0x1da2" "0xaae0" 
 4414.247640] erlangen alsactl[25044]: Hardware is initialized using a generic method 
 4414.247841] erlangen alsactl[25044]: No state is present for card HDMI 
 4414.248484] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
 4571.171926] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
 4571.180328] erlangen systemd[1]: alsa-restore.service: Succeeded. 
 4571.180569] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    4.169741] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    5.176246] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
[39804.503019] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
[39804.659361] erlangen systemd[1]: alsa-restore.service: Succeeded. 
[39804.693975] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    3.997118] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    4.006577] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
 7490.089895] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
 7490.159818] erlangen systemd[1]: alsa-restore.service: Succeeded. 
 7490.159854] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    4.206307] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    4.206920] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
  706.282263] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
  706.341550] erlangen systemd[1]: alsa-restore.service: Succeeded. 
  706.341607] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    3.951424] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    3.960400] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
 5446.533344] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
 5446.598257] erlangen systemd[1]: alsa-restore.service: Succeeded. 
 5446.598301] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    4.104103] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    5.115009] erlangen systemd[1]: Finished Save/Restore Sound Card State. 
 1079.906456] erlangen systemd[1]: Stopping Save/Restore Sound Card State... 
 1079.991763] erlangen systemd[1]: alsa-restore.service: Succeeded. 
 1079.991847] erlangen systemd[1]: Stopped Save/Restore Sound Card State. 
    4.898650] erlangen systemd[1]: Starting Save/Restore Sound Card State... 
    4.914583] erlangen systemd[1]: Finished Save/Restore Sound Card State.


It had none of /etc/alsa/state-daemon.conf or /var/lib/alsa/asound.state. IIRC running “/usr/sbin/alsactl store” fixed that.

Apart plymouth-start.service yes.

It fixes under Leap 15.2 but not on Tumbleweed (at least on MacBookPro9,2), hence my searches of finding how to apply custom settings to alsa when booting up.
As stated previously, alsa creates a /var/lib/alsa/asound.state with default settings as its trying to restore before the sound card driver is fully loaded.

Anyway, things are fixed now but making this consistent is better (other distributions also are affected; found forum’s threads where Debian, Arch, Manjaro, etc. users does have the same problem), be it a rolling release or not.

Host erlangen is fine, but the bug shows up at host 3400G. Fixed the ordering by inserting two lines in alsa-restore.service:

3400G:~ # diff /usr/lib/systemd/system/alsa-restore.service /etc/systemd/system/alsa-restore.service
10a11,12
> Requires=sound.target
> After=sound.target
3400G:~ # 

and changing one line in sound-extra.service:

3400G:~ # diff /usr/lib/systemd/system/sound-extra.service /etc/systemd/system/sound-extra.service
3c3
< After=alsasound.service
---
> After=sound.target
3400G:~ # 


3400G:~ # systemctl status sound-extra.service 
● sound-extra.service - Load extra kernel modules for sound stuff
     Loaded: loaded (/etc/systemd/system/sound-extra.service; static)
     Active: inactive (dead) since Fri 2020-11-27 14:43:44 CET; 8min ago
    Process: 753 ExecStart=/usr/lib/systemd/scripts/load-sound-modules.sh (code=exited, status=0/SUCCESS)
   Main PID: 753 (code=exited, status=0/SUCCESS)

Nov 27 14:43:44 3400G systemd[1]: Starting Load extra kernel modules for sound stuff...
Nov 27 14:43:44 3400G systemd[1]: sound-extra.service: Succeeded.
Nov 27 14:43:44 3400G systemd[1]: Finished Load extra kernel modules for sound stuff.
3400G:~ # systemctl status alsa-restore.service 
● alsa-restore.service - Save/Restore Sound Card State
     Loaded: loaded (/etc/systemd/system/alsa-restore.service; static)
     Active: active (exited) since Fri 2020-11-27 14:43:44 CET; 8min ago
    Process: 752 ExecStart=/usr/sbin/alsactl restore (code=exited, status=0/SUCCESS)
   Main PID: 752 (code=exited, status=0/SUCCESS)

Nov 27 14:43:44 3400G systemd[1]: Starting Save/Restore Sound Card State...
Nov 27 14:43:44 3400G systemd[1]: Finished Save/Restore Sound Card State.
3400G:~ # 

Wunderbar karlmistelberger! Your changes have made this working if the sound card isn’t configured by YaST.

The S/PDIF is finally disabled across reboots:

  1. if the sound card is flagged as not configured by YaST’s sound panel
  2. a turd file */etc/alsa/state-daemon.conf *
    exists. 1. muting S/PDIF channels on alsamixer(1)
  3. saving alsa’s state with sudo alsactl store

What are the changes YaST did? Thanks to snapper, I could track down the changes:

--- /.snapshots/221/snapshot/etc/modprobe.d/50-sound.conf    2020-11-22 15:23:27.886986630 +0100
+++ /.snapshots/222/snapshot/etc/modprobe.d/50-sound.conf    2020-11-27 20:39:57.512873633 +0100
@@ -1,4 +1 @@
 
-options snd slots=snd-hda-intel
-# u1Nb.RlhQY3YvZ59:7 Series/C216 Chipset Family High Definition Audio Controller
-alias snd-card-0 snd-hda-intel

A big thank you for helping fixing this :wink:

Many thanks for pointing to ‘yast2 sound’. I was not aware of this. :wink:

https://bugzilla.opensuse.org/show_bug.cgi?id=1179363

Good job and thanks again for looking into this :wink:

One last word about that thread, Macs by default outputs a sound when it boots (called “startup chime” in Apple’s world). If that sound is muted, then the workarounds we have found have to be applied; otherwise no tweaks are needed (be it the sound card is marked as configured or not in YaST’s sound panel)!

Testing was done on two MacBook Pro (a Mid-2012 with an i5 which hasn’t its startup chime muted and a Mid-2012 with an i7 which has its startup chime muted).

To summarize it appears muting the startup chime disable the sound card on Macs’s UEFI, thus default settings on Tumbleweed aren’t good and tweaks have to be done. Dumping efivars on both laptops was of no help, those are equals.

I don’t have a bugzilla’s account (yet!), would you mind please update your PR by adding this note?

There is much interesting detail. I think it’s good practice to wait for sound.target being reached. It ensures required units are loaded and active before further action is taken:

**erlangen:~ #** systemctl list-units '*sound*' 
  UNIT                                                                LOAD   ACTIVE SUB     DESCRIPTION                                              
  sys-devices-pci0000:00-0000:00:01.0-0000:01:00.1-sound-card1.device loaded active plugged Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X]  
  sys-devices-pci0000:00-0000:00:1f.3-sound-card0.device              loaded active plugged 100 Series/C230 Series Chipset Family HD Audio Controller
  sound.target                                                        loaded active active  Sound Card                                                

LOAD   = Reflects whether the unit definition was properly loaded. 
ACTIVE = The high-level unit activation state, i.e. generalization of SUB. 
SUB    = The low-level unit activation state, values depend on unit type. 

**3 loaded units listed.** Pass --all to see loaded but inactive units, too. 
To show all installed unit files use 'systemctl list-unit-files'. 
**erlangen:~ #**

I don’t have a bugzilla’s account (yet!), would you mind please update your PR by adding this note?
Login to bugzilla with forum credentials should work.

I agree, no matter what computer is.

Ah cool thanks I wasn’t aware of this :wink: