Lange Zeit habe ich das Problem vor mir hergeschoben, da ich einen Workaround (alter NVIDIA-Treiber 295.71) gefunden habe. Nun, nach der Arch Linux Umstellung von sysvinit auf systemd und der Einführung vom Kernel 3.6 führt nur ein sehr mühsamer Weg an dem neuen NVIDIA-Treiber 304.64 sowie 304.60, 304.51, 304.43, 304.37, 304.32, 302.17 (Stand: 8. November 2012) vorbei. Daher habe ich mich nun mit dem Problem intensivst auseinander gesetzt und eine Lösung gefunden!
Problem: Nach einem Suspend to RAM wird kein Ton per HDMI ausgeben!
Vermutung: Es hat sehr wahrscheinlich mit der Einschaltreihenfolge (TV, AVR / Verstärker, Media-PC) zu tun. Diese Analyse möchte ich hier nun nicht weiter breit treten, da ihr sie im Arch Linux Forum findet.
Lösung: Glücklicherweise bin ich gestern ziemlich schnell auf einen Thread im VDR-Portal gestoßen. Dort lieferte mir steffen_b den perfekten Denkanstoß – xrandr ist das Zauberwort!
Um einen xrandr Befehl automatisch nach dem Suspend auszuführen, müssen wir ein Skript anlegen – eine sogenannte Hook. Jetzt kommt aber erschwerend hinzu, dass die meisten Distributionen pm-utils also pm-suspend für den Bereitschaftsmodus verwenden, Arch Linux in der aktuellsten Version (Stand: 8. November 2012) hingegen verwendet dank systemd nun systemctl suspend (systemd-suspend).
Das heißt, erstmal müssen wir herausfinden, wie unser System in den Bereitschaftsmodus, beim Auswählen von Bereitschaft oder Suspend, wechselt. Dazu führen wir folgenden Befehl aus:
journalctl -b -u systemd-suspend
Kommt nun …
-bash: journalctl: Kommando nicht gefunden.
… setzt eure Distribution noch auf pm-suspend. Um es noch mal zu verifizieren könnte man ein …
tail -n 1 /var/log/pm-suspend.log
… machen, wird hier das aktuelle Datum angezeigt, vorausgesetzt euer System ist vor kurzem aus dem S3-Modus erwacht, wird pm-suspend verwendet.
Sollte allerdings der journalctl Befehl folgenden Output liefern …
Nov 08 00:13:37 elfriede systemd-sleep[7181]: Suspending system...
… setzt eure Distribution bereits auf systemd-suspend.
So, hier nun die jeweilige Hook (Skript), denn ihr wisst ja jetzt, ob ihr eine PM-Hook (pm-suspend) oder eine SystemD-Hook (systemd-suspend) benötigt.
PM-Hook (Ubuntu, Linux Mint, Debian, yaVDR, XBMCbuntu, Fedora, etc.)
Info: Fedora (17) setzt zwar auf systemd, aber der Suspend wird noch von pm-utils durchgeführt.
vi /etc/pm/sleep.d/00nvidia
#!/bin/bash # # NVIDIA Bugfix - kein Sound nach S3 #################################### nvidia_bug() { for X in /tmp/.X11-unix/*; do DISPLAY=`echo $X | sed s#/tmp/.X11-unix/X#:#` USER=`who | grep -m1 "($DISPLAY)" | awk '{print \$1}'` #USER=USERNAME OUTPUT=`su -l -c "xrandr -display $DISPLAY -q | grep ' connected ' | awk '{print \\$1}'" $USER` for PORT in $OUTPUT; do su -l -c "xrandr -display $DISPLAY --output $PORT --off" $USER su -l -c "xrandr -display $DISPLAY --output $PORT --auto" $USER echo -e "Port-Reset für $DISPLAY an $PORT mit $USER durchgeführt" done done } case "${1}" in suspend|hibernate) ;; resume|thaw) nvidia_bug ;; esac
chmod 755 /etc/pm/sleep.d/00nvidia
SystemD-Hook (aktuelles Arch Linux)
vi /usr/lib/systemd/system-sleep/nvidia.sh
#!/bin/bash # # NVIDIA Bugfix - kein Sound nach S3 #################################### nvidia_bug() { for X in /tmp/.X11-unix/*; do DISPLAY=`echo $X | sed s#/tmp/.X11-unix/X#:#` USER=`who | grep -m1 "($DISPLAY)" | awk '{print \$1}'` #USER=USERNAME OUTPUT=`su -l -c "xrandr -display $DISPLAY -q | grep ' connected ' | awk '{print \\$1}'" $USER` for PORT in $OUTPUT; do su -l -c "xrandr -display $DISPLAY --output $PORT --off" $USER su -l -c "xrandr -display $DISPLAY --output $PORT --auto" $USER echo -e "...Port-Reset für $DISPLAY an $PORT mit $USER durchgeführt..." echo "=== ENDE ===" done done } case $1/$2 in pre/*) echo "nvidia.sh going to $2..." echo "...nichts zu tun..." ;; post/*) echo "nvidia.sh - waking up from $2..." nvidia_bug ;; esac
chmod 755 /usr/lib/systemd/system-sleep/nvidia.sh
Der erste xrandr Befehl schaltet den jeweiligen Port aus, der zweite schaltet ihn wieder ein. Der Rest sind eigentlich nur Variablen, diese sollen die benötigten Angaben wie Nummer des X-Servers (:0), Benutzer der die Desktopumgebung (nhartung) und Monitoranschluss (HDMI-0) selbstständig herausfinden, damit die wenigsten von euch die Hook noch händisch anpassen müssen.
Bei den meist verbreitetsten Linux-Distributionen (Ubuntu, Debian, Fedora, Linux-Mint, etc.) sollte die Hook ohne Änderungen funktionieren. Bei speziell angepassten Distributionen, wie zum Beispiel yaVDR oder bei meinem Arch Linux System, muss eine Variable ausgetauscht werden! Den etwas erfahreneren Usern unter euch wird es in der Hook bereits aufgefallen sein, es handelt sich um die USER Variable. Bei yaVDR kommentiert man USER=`who...
in der Hook aus, entfernt dann die # vor der zweiten USER Variable und ersetzt dort USERNAME mit dem User, der die Desktopumgebung / Media-Center-Umgebung startet – bei yaVDR ist es root.
#USER=`who | grep -m1 "($DISPLAY)" | awk '{print \$1}'` USER=root
Bei meinen speziellen Arch Linux – XBMC Media-PC ist es:
#USER=`who | grep -m1 "($DISPLAY)" | awk '{print \$1}'` USER=nhartung
Bei euch ist es?
So, das sollte es gewesen sein, beim nächsten Aufwachen aus dem Bereitschaftsmodus sollte euer Ton wieder funktionieren. Viel Spaß! 😉
Bei Problemen oder Fragen, gerne Fragen – auch wenn es um weitere spezielle Linux-Distributionen geht!
PS: Systemd ist echt der Hammer, das Booten geht wesentlich schneller wie mit sysvinit – klar an die Verwaltung muss man sich erst gewöhnen, aber so ist das mit allen neuen Sachen.
Hi Nico !
Na dann hab ich doch gleich mal die erste Frage 🙂
Vorerst , das ganze funktioniert super , eine tolle Arbeit von dir !!!
Leider übernimmt er nachdem aufwachen nicht , die Refreshrate , das heisst das TV Bild läuft dann bei mir mit 60Hz statt der eigentlichen 50Hz …
Im VDR Portal wurde ja einiges beschrieben , aber ein nvidia-settings befehl im script einzubauen hat nicht funktioniert !
Ich wollte es jetzt evt. nochmal mit xrandr versuchen die rate auf 50 zusetzen , aber evt. hast du ja eine etwas andere zündene Idee für mich 🙂
Viele Grüsse
Dennis
Hi Dennis, ne ich habe auch keine andere Idee – würde es auch mit xrandr machen. 😉
Gruß
Ok 🙂
Dann probiere ich nach hder nach der Arbeit nochmal rum !
Wie genau der allerdings lauten muss und wie man das macht wüsste ich jetzt ehrlich gesagt nicht , da ich mich mit dem Bash scripts nicht auskenne , aber es Hochinteressant finde 😉
su -l -c „xrandr -display $DISPLAY –output $PORT –auto“ $USER (auto bewirkt ja das er zu den Default werten geht , welche bei mir leider 60Hz sind …
Könnte man statt dem –auto ein –rate 50 anfügen oder ist die Sache mit dem Ton dann vorbei ? 🙂
Am besten wäre es die Defaultwerte zu ändern !!! Aber ich hab keine Ahnung ob dies möglich wäre :-/
Gruss
Dennis
Hi Dennis, ja genau – fast so. 😉
Gib einfach mal am Media-PC direkt, nicht per SSH,
xrandr
ein – da siehst du alle möglichen Einstellungen (Auflösung und Wiederholfrequenz) die dein TV unterstützt.Dann editierst du das Bash-Skript und anstelle von
--auto
, machst du dann--mode 1920x1080 --rate 50
oder
--mode 1920x1080@50
.
Viel Glück, Nico
PS: Teste es am besten erst mal direkt am Media-PC, wenn es dann passt, editierst du das Bash-Skript.