Der Ärger mit dem Ton

Achtung: Mikrofon weiterhin ungetestet

Aktueller Hinweis

Seit ich auf Kernelversion 2.6.31.1 umgestiegen bin, funktioniert der Ton problemlos. Erkannt wird nurnoch der ALC888 Codec, d.h. es treten keine Probleme mehr mit den Mixerelementen auf. Lädt man das Modul nun mit folgenden Parametern, schalten die Notebooklautsprecher korrekt ab, sobald ein Kopfhörer eingesteckt wird:
Seeschlange:~# modprobe snd-hda-intel enable_msi=1 model=laptop
Damit der Ton auch über HDMI ausgegeben wird, ist auch bei neueren Kernelversionen der zusätzliche probe_mask=0x5-Parameter notwendig. Um die Soundkarte dauerhaft richtig zu konfigurieren, kann folgender Befehl verwendet werden:
Seeschlange:~# echo options snd-hda-intel enable_msi=1 model=laptop probe_mask=0x5 >> /etc/modprobe.d/snd-hda-intel.conf
Die Änderungen sind dann nach einem Neustart verfügbar. Alternativ kann das Modul natürlich auch manuell entfernt und erneut geladen werden.

Vorwort

Ich bin seit Jahren eingefleischter Linuxfan, benutzte dafür jedoch häufig nur ältere Hardware. So dass sich viele Probleme durch updaten von Kernel oder Userspace lösen ließen oder sich im Internet viele hilfreiche Ansätze fanden. Nach dem Kauf eines neuen Notebooks verzweifelte ich jedoch bereits beim Einrichten der Soundkarte - ein Problem, dass mich kurz vor die Windowsinstallation trieb. So weit ist es glücklicherweise nicht gekommen, obwohl das Ergebnis auch heute noch nicht so ist, wie ich es mir wünschen würde.
Vorab sei gesagt, dass ich mich hier nicht auf die Einrichtung eines Surroundsystems beziehe, sondern nur eine Audioausgabe auf Notebooklautsprechern und Kopfhörern wünsche. Funktioniert die Lautstärkeregelung auch noch, bin ich zufrieden.

Das Kompilieren eines eigenen Kernels ist nicht schwierig, allerdings erfordet es ein gewisses Verständnis über die eingesetzte Distribution. Viele Distributionen verwenden extrem verpatchte Kernel, damit es beim Hochfahren schön bunt ist oder (wenigstens sinnvoll) die Installation auf jedem System funktioniert. Man sollte sich also vor der Arbeit am Kernel sicher sein, dass man über die Quellcodes des aktuell eingesetzten Kernels verfügt. Ansonsten kann es im schlimmsten Fall dazu führen, dass das System nicht mehr hochfährt. Für erfahrene Anwender stellt sich kein Problem dar, für Einsteiger ist es Grund für eine Neuinstallation.

Kernel kompilieren - Teil 1

Die erste große Frage war natürlich, welche Hardware im Notebook verbaut ist. Dies lässt sich relativ leicht feststellen:
michael@Seeschlange:~$ lspci | grep Audio
00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 04)
michael@Seeschlange:~$ 
Screenshot
Also eine Intel HD Karte, die sich im Kernel unter Device Drivers -> Sound -> Advanced Linux Sound Architecture -> PCI devices -> Intel HD Audio finden lässt. Sicherheitshalber werden erstmal alle Codecs mitkompiliert.

Nachdem kompilieren des Kernels mit

make modules && make modules_install
lässt sich das frische Modul hoffentlich einbinden. Hier stieß ich auf mein erstes Problem:
Seeschlange:~# modprobe snd-hda-intel
Seeschlange:~# dmesg | tail
ACPI: PCI Interrupt 0000:00:1b.0[A] -> GSI 22 (level, low) -> IRQ 22
PCI: Setting latency timer of device 0000:00:1b.0 to 64
hda_codec: Unknown model for ALC883, trying auto-probe from BIOS...
hda_codec: Unknown model for ALC268, trying auto-probe from BIOS...
hda_codec: Cannot set up configuration from BIOS.  Using base mode...SPDIF already defined
ACPI: PCI interrupt for device 0000:00:1b.0 disabled
HDA Intel: probe of 0000:00:1b.0 failed with error -16Seeschlange:~# 
Das Modul wurde also erfolgreich geladen, konnte die Soundkarte jedoch nicht aktivieren. Nach einigem Probieren fand ich dann die Lösung: Der Treiber sollte theoretisch selbstständig erkennen, welche Hardware vorhanden ist, funktioniert das, so wie hier, nicht, kann man ihm mit einem Parameter auf die Sprünge helfen:
Seeschlange:~# rmmod snd-hda-intel; modprobe snd-hda-intel model=medion
Seeschlange:~# dmesg | tail
ACPI: PCI Interrupt 0000:00:1b.0[A] -> GSI 22 (level, low) -> IRQ 22
PCI: Setting latency timer of device 0000:00:1b.0 to 64
hda_codec: Unknown model for ALC268, trying auto-probe from BIOS...
hda_codec: Cannot set up configuration from BIOS.  Using base mode...Seeschlange:~# 
Das sieht schon etwas besser aus, allerdings ging es noch besser:
Seeschlange:~# rmmod snd-hda-intel; modprobe snd-hda-intel model=acer
Seeschlange:~# dmesg | tail
ACPI: PCI Interrupt 0000:00:1b.0[A] -> GSI 22 (level, low) -> IRQ 22
PCI: Setting latency timer of device 0000:00:1b.0 to 64
Seeschlange:~# 
Keine Fehlermeldungen mehr, die Karte scheint richtig "erkannt" wurden zu sein und der Kernel scheint sie zu akzeptieren - Hübsch! Letztendlich ist Ausprobieren angesagt. Eine vollständige Auflistung der unterstützten Modelle findet man in der Kerneldokumentation (häufig /usr/src/linux/Documentation/sound/alsa/ALSA-Configuration.txt) im Abschnitt "Module snd-hda-intel".

Hat man die perfekte Einstellung gefunden, sollte dies dem System dauerhaft beigebracht werden - das ist jedoch von Distribution zu Distribution anders realisierbar. Unter Debian und vielen anderen, ist es mit einem

Seeschlange:~# echo options snd-hda-intel model=acer > /etc/modprobe.d/snd-hda-intel-myoptions
bereits getan.

Wer Glück hat, kann die Soundkarte benutzen. Diverse Googleergebnisse zeigen jedoch, dass es häufig nicht ganz so einfach ist...

Kernel kompilieren - Teil 2

...denn aktuelle Soundkarten verfügen über mehrere Soundchips, mit teilweise gleichen Bezeichnungen und damit kann das ALSA-System momentan noch nicht umgehen. Ob dieses Problem besteht, zeigt ein sehr einfacher Versuch:
michael@Seeschlange:~$ alsamixer 
ALSA lib simple_none.c:1591:(simple_add1) helem (MIXER,'Headphone 
Playback Switch',0,2,0) appears twice or more

alsamixer: function snd_mixer_load failed: Invalid argument
Erscheint dieser oder ein ähnlicher Fehler, ist man betroffen und ab hier helfen leider keine Parameter oder (zum heutigen Stand der Dinge) Updates. Der Fehler wird auf Grund oben beschriebener Sachlage verursacht und liegt in den ALSA-Bibliotheken. Da es jedoch einfacher ist den Kernel zu patchen (ein großer Vorteil von Linux gegenüber Windows), gehe ich den einfachsten Weg: (den schließlich soll das Notebook ja endlich mal ein Tönchen ausspucken)

Erstmal sollte man sich darüber bewusst werden, welchen Codec die Soundkarte verwendet. Dies ist mit

michael@Seeschlange:~$ cat /proc/asound/Intel/codec#?|grep Codec
Codec: Realtek ALC888
Codec: Realtek ALC268
michael@Seeschlange:~$ 
schnell gemacht. In meinem Fall handelt es sich um die Realtekcodecs ALC888 und ALC268. Ausgehend von der Fehlermeldung des alsamixers scheinen beide ein Mixerelement anzubieten, dass sich "Headphone Playback Switch" nennt. Das Problem ist erkannt, die Ursache gefunden, nun geht's an die Lösung: Dazu muss in einem Editor die Datei

/usr/src/linux/sound/pci/hda/patch_realtek.c

geöffnet und in ihr die Zeichenkette "Headphone Playback Switch" gesucht werden (je nach Codechersteller ist natürlich eine andere Datei in diesem Verzeichnis zu wählen). Erfahrungsgemäß kommt diese Zeichenkette viele Male vor, ist jedoch nur einmal für das Problem verantwortlich.

Die Datei, es handelt sich übrigens um Quellcode der Programmiersprache C, ist in mehrere Blöcke unterteilt. Diese Blöcke orientieren sich im Allgemeinen an den diversen Codecs. Findet man die gesuchte Zeichenkette, sollte also sichergestellt werden, dass wenige Zeilen darüber die Codecbezeichnung (Liebe C-Programmierer, bitte schlagt mich nicht, für diese schlechte Beschreibung) steht - ansonsten macht man sich unnötige Arbeit. In meinem Fall, sieht es so aus:

static struct snd_kcontrol_new alc268_base_mixer[] = {	/* output mixer control */
	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
	HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
	{ }
};
In der roten Zeile ist die Codecbezeichnung versteckt, in der gelben liegt die problematische Bezeichnung. In dieser Zeile muss auch "Headphone Playback Switch" durch etwas anderes, z.B. "Kopfhoererschalter" ersetzt werden. Das war's! Datei speichern und schließen und das Kernelmodul erneut mittels
Seeschlange:/usr/src/linux# rm sound/pci/hda/patch_realtek.o
Seeschlange:/usr/src/linux# make modules && make modules_install
Seeschlange:/usr/src/linux# rmmod snd-hda-intel; modprobe snd-hda-intel
Seeschlange:/usr/src/linux# 
kompilieren und neu laden. Die Wahrscheinlichkeit, dass der Alsamixer sofort startet ist gering, da in den meisten Fällen mehrere Mixerelemente umbenannt werden müssen. Wird exakt das gleiche Element angezeigt, wie das eben veränderte, so erfolgte die Änderung an der falschen Stelle. Einfach nochmal suchen und notfalls alle Vorkommen ändern!

Das Ändern der Zeichenketten hat normalerweise keine Auswirkungen auf die Systemstabilität. Idealerweise sollten trotzdem nur sowenig Zeichenketten geändert werden, wie irgendwie möglich.

(Mein) Offenes Problem

Leider ist das Soundprojekt auf meinem Notebook noch nicht abgeschlossen. Wenn ich im Mixer "Headphones" aktiviere, so liegt auf dem Kopfhöreranschluss meines Notebooks ein entsprechendes Signal an. Dabei handelt es sich um eine exakte Kopie des Signals der Frontlautsprecher. Damit könnte ich leben, allerdings schalten diese nicht ab, wenn Kopfhörer eingesteckt sind und das Setzten des Stummschalters für die Frontlautsprecher des Notebooks lässt gleichzeitig die Kopfhörer verstummen.

Die Codecs der zwei Soundchips weisen darauf hin, dass mein Notebook viel mehr kann. Theoretisch sollte es nicht nur möglich sein die Frontlautsprecher abzuschalten, sondern auch individuelle Inhalte auf Notebook und Kopfhörer zu verteilen. Damit wäre 7.1er Surround möglich.

michael@Seeschlange:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Intel [HDA Intel], device 0: ALC883 Analog [ALC883 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 5: ALC268 Analog [ALC268 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
michael@Seeschlange:~$ 
Findet beide Devices, allerdings bleibt die Ausgabe auf hw:0,5 stumm. Für die Lösung des Problems fehlt mir zur Zeit noch das genaue Verständnis der eingesetzten Codecs und der Funktionsweise von ALSA. Für Hinweise wäre ich dankbar!

Die Lösung wird dann natürlich an dieser Stelle veröffentlicht!


Kommentare

Neue Kommentare sind aus Spamgründen leider nicht möglich.
SebastianSebastian
am 07.06.2009 um 18:09 Uhr
Habe in die alsa-base als letzte Zeile eingetragen: options snd-hda-intel model=lenovo danach ging bei mir Ubuntu 8.04 auch die Sache mit dem Kopfhörerausgang.

Ingo S.Ingo S.
am 29.10.2008 um 10:13 Uhr
Hi.

Nun mal eine Anmerkung von mir. Mit linux habe ich es noch nicht so, aber es gab 3,5" Stereoklinken > hier die für den Kopfhörer wo automatisch auf stumm geschaltet wird > nicht per Signal, sondern auch manuel! D.h. sofern ein Kopfhörer eingestöpselt ist, wurden die internen Lautsprecher ausgestellt / abgestellt. Bitte um evtl. berücksichtigung, nicht das ihr nach einem Fehler sucht der keine richtiger ist bzw. habe ich es schon ein mal gehabt, das die klicke und/oder der Stecker nicht mehr ganz astrein waren, und deshalb der Ton mit an blieb (ist aber schon lange her)... .

Evtl. hilft es ja.



MfG

Ingo S.