Solved [Solved] Switch audio output when speakers are connected

Hi guys,

I'm quite new to FreeBSD (long time Linux user (Slackware)) and I find it pretty amazing (I'm especially intrigued by ZFS). I was struggling with a few things but I managed to make them work eventually. There are, however, several things which still give me a hard time and one of them is this audio issue.

My Asus N750JV built-in speakers work OK but if I plug in external speakers the audio output isn't switched automatically. After a bit of searching I found that in FreeBSD these things are handled via sysctl(8). My sysctl -a | grep hw.snd reads:

Code:
hw.snd.report_soft_formats: 1
hw.snd.report_soft_matrix: 1
hw.snd.latency: 5
hw.snd.latency_profile: 1
hw.snd.vpc_autoreset: 1
hw.snd.vpc_0db: 45
hw.snd.vpc_reset: 0
hw.snd.compat_linux_mmap: 0
hw.snd.feeder_eq_presets: PEQ:16000,0.2500,62,0.2500:-9,9,1.0:44100,48000,88200,96000,176400,192000
hw.snd.feeder_eq_exact_rate: 0
hw.snd.feeder_rate_presets: 100:8:0.85 100:36:0.92 100:164:0.97
hw.snd.feeder_rate_polyphase_max: 183040
hw.snd.feeder_rate_min: 1
hw.snd.feeder_rate_max: 2016000
hw.snd.feeder_rate_round: 25
hw.snd.feeder_rate_quality: 1
hw.snd.vpc_mixer_bypass: 1
hw.snd.verbose: 0
hw.snd.default_auto: 1
hw.snd.version: 2009061500/amd64
hw.snd.default_unit: 1
hw.snd.maxautovchans: 16

and cat /dev/sndstat

Code:
Installed devices:
pcm0: <Intel (0x2807) (HDMI/DP 8ch)> (play)
pcm1: <Realtek (0x0668) (Internal Analog)> (play/rec) default
pcm2: <Realtek (0x0668) (Right Analog)> (play/rec)
pcm3: <Realtek (0x0668) (Right Digital)> (play)

Setting hw.snd.default_unit to 2 works but I would really appreciate if this was done automatically. Setting this manually to 2 and then back to 1 every time is quite annoying. I tried to set hw.snd.default_auto to 2 but that didn't work. I wasn't able to google anything else. Please, how can I do this?
 
Re: Automaticly switch audio output when speakers are connec

Have a look in the snd_hda(4) man page. The driver is pretty generic but implementation details can be different from board to board. So you may need to "re-route" certain signals.
 
Re: Automaticly switch audio output when speakers are connec

SirDice said:
Have a look in the snd_hda(4) man page...........

Thank you, could you also help me determine the correct cad%d and nid%d (mentioned in man page)? I tried to use those from Example 2 but it didn't work. How do I find the correct values?
 
Re: Automaticaly switch audio output when speakers are conne

ondra_knezour said:
... set the hw.snd.verbose sysctl to 2 and then cat /dev/sndstat.
Ok, this is becoming quite complicated for me:
Code:
FreeBSD Audio Driver (64bit 2009061500/amd64)
Installed devices:
pcm0: <Intel (0x2807) (HDMI/DP 8ch)> on hdaa0  (1p:1v/0r:0v)
	snddev flags=0x2e7<SIMPLEX,AUTOVCHAN,SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,VPC>
	[pcm0:play:dsp0.p0]: spd 48000, fmt 0x00200010, flags 0x00006100, 0x00000004
	interrupts 580, underruns 0, feed 580, ready 0 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x6100<BUSY,HAS_VCHAN,VCHAN_PASSTHROUGH>
	{userland} -> feeder_mixer(0x00200010) -> {hardware}
	pcm0:play:dsp0.p0[pcm0:virtual:dsp0.vp0]: spd 44100/48000, fmt 0x00200010, flags 0x10000000, 0x00000029
	interrupts 0, underruns 0, feed 0, ready 0 [b:0/0/0|bs:65536/2048/32]
	channel flags=0x10000000<VIRTUAL>
	{userland} -> feeder_root(0x00200010) -> feeder_volume(0x00200010) -> feeder_rate(0x00200010 q:1 44100 -> 48000) -> {hardware}
pcm1: <Realtek (0x0668) (Internal Analog)> on hdaa1  (1p:1v/1r:1v) default
	snddev flags=0x2e2<AUTOVCHAN,BUSY,MPSAFE,REGISTERED,VPC>
	[pcm1:play:dsp1.p0]: spd 48000, fmt 0x00200010, flags 0x00002100, 0x00000004
	interrupts 568, underruns 0, feed 568, ready 0 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x2100<BUSY,HAS_VCHAN>
	{userland} -> feeder_mixer(0x00200010) -> {hardware}
	pcm1:play:dsp1.p0[pcm1:virtual:dsp1.vp0]: spd 44100/48000, fmt 0x00200010, flags 0x10000000, 0x00000029
	interrupts 0, underruns 0, feed 0, ready 0 [b:0/0/0|bs:65536/2048/32]
	channel flags=0x10000000<VIRTUAL>
	{userland} -> feeder_root(0x00200010) -> feeder_volume(0x00200010) -> feeder_rate(0x00200010 q:1 44100 -> 48000) -> {hardware}
	[pcm1:record:dsp1.r0]: spd 48000, fmt 0x00200010, flags 0x00002100, 0x00000005
	interrupts 533, overruns 0, feed 1066, hfree 4096, sfree 4096 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x2100<BUSY,HAS_VCHAN>
	{hardware} -> feeder_root(0x00200010) -> feeder_mixer(0x00200010) -> {userland}
	pcm1:record:dsp1.r0[pcm1:virtual:dsp1.vr0]: spd 44100/48000, fmt 0x00200010, flags 0x10000000, 0x00000029
	interrupts 0, overruns 0, feed 0, hfree 0, sfree 65536 [b:0/0/0|bs:65536/2048/32]
	channel flags=0x10000000<VIRTUAL>
	{hardware} -> feeder_root(0x00200010) -> feeder_rate(0x00200010 q:1 48000 -> 44100) -> feeder_volume(0x00200010) -> {userland}
pcm2: <Realtek (0x0668) (Right Analog)> on hdaa1  (1p:1v/2r:1v)
	snddev flags=0x2e2<AUTOVCHAN,BUSY,MPSAFE,REGISTERED,VPC>
	[pcm2:play:dsp2.p0]: spd 48000, fmt 0x00200010, flags 0x00002100, 0x00000004
	interrupts 555, underruns 0, feed 555, ready 0 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x2100<BUSY,HAS_VCHAN>
	{userland} -> feeder_mixer(0x00200010) -> {hardware}
	pcm2:play:dsp2.p0[pcm2:virtual:dsp2.vp0]: spd 44100/48000, fmt 0x00200010, flags 0x10000000, 0x00000029
	interrupts 0, underruns 0, feed 0, ready 0 [b:0/0/0|bs:65536/2048/32]
	channel flags=0x10000000<VIRTUAL>
	{userland} -> feeder_root(0x00200010) -> feeder_volume(0x00200010) -> feeder_rate(0x00200010 q:1 44100 -> 48000) -> {hardware}
	[pcm2:record:dsp2.r0]: spd 48000, fmt 0x00200010, flags 0x00002100, 0x00000005
	interrupts 0, overruns 0, feed 0, hfree 4096, sfree 4096 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x2100<BUSY,HAS_VCHAN>
	{hardware} -> feeder_root(0x00200010) -> feeder_mixer(0x00200010) -> {userland}
	[pcm2:record:dsp2.r1]: spd 44100, fmt 0x00200010, flags 0x00000000, 0x00000021
	interrupts 0, overruns 0, feed 0, hfree 4096, sfree 65536 [b:4096/2048/2|bs:65536/2048/32]
	channel flags=0x0
	{hardware} -> feeder_root(0x00200010) -> feeder_volume(0x00200010) -> {userland}
	pcm2:record:dsp2.r0[pcm2:virtual:dsp2.vr0]: spd 8000, fmt 0x00100008, flags 0x10000000, 0x00000000
	interrupts 0, overruns 0, feed 0, hfree 0, sfree 0 [b:0/0/0|bs:0/0/0]
	channel flags=0x10000000<VIRTUAL>
	{hardware} -> feeder_root(0x00000000) -> {userland}
pcm3: <Realtek (0x0668) (Right Digital)> on hdaa1  (1p:1v/0r:0v)
	snddev flags=0x2e7<SIMPLEX,AUTOVCHAN,SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,VPC>
	[pcm3:play:dsp3.p0]: spd 48000, fmt 0x00200010, flags 0x00006100, 0x00000004
	interrupts 543, underruns 0, feed 543, ready 0 [b:4096/2048/2|bs:4096/2048/2]
	channel flags=0x6100<BUSY,HAS_VCHAN,VCHAN_PASSTHROUGH>
	{userland} -> feeder_mixer(0x00200010) -> {hardware}
	pcm3:play:dsp3.p0[pcm3:virtual:dsp3.vp0]: spd 44100/48000, fmt 0x00200010, flags 0x10000000, 0x00000029
	interrupts 0, underruns 0, feed 0, ready 0 [b:0/0/0|bs:65536/2048/32]
	channel flags=0x10000000<VIRTUAL>
	{userland} -> feeder_root(0x00200010) -> feeder_volume(0x00200010) -> feeder_rate(0x00200010 q:1 44100 -> 48000) -> {hardware}
The only thing I know is only pcm1 and pcm2 are relevant since setting hw.snd.default_unit to 1 makes the sound go to internal speakers and 2 makes it go to external speakers/headphones/whatever is plugged in. I have no clue about how to transform this output to device hints mentioned in snd_hda().
 
Re: Automaticaly switch audio output when speakers are conne

Based on manpage I would expect nice table with soundcards I/O :) what would be printed on first console (also may be checked with dmesg) when you unload and reload the snd_hda driver with kldunload(8)/kldload(8)?
 
Re: Automaticaly switch audio output when speakers are conne

ondra_knezour said:
Based on manpage I would expect nice table with soundcards I/O :) what would be printed on first console (also may be checked with dmesg) when you unload and reload the snd_hda driver with kldunload(8)/kldload(8)?
Hi and thanks again :) .
I'm afraid this isn't possible since I'm running a custom kernel and snd_hda is compiled into it. So the kldunload snd_hda says
Code:
kldunload: can't find file snd_hda
and kldload snd_hda says
Code:
kldload: can't load snd_hda: File exists
Nothing appears on the first console.
dmesg() only says
Code:
hdacc0: <Intel (0x2807) HDA CODEC> at cad 0 on hdac0
hdaa0: <Intel (0x2807) Audio Function Group> at nid 1 on hdacc0
pcm0: <Intel (0x2807) (HDMI/DP 8ch)> at nid 3 on hdaa0
hdacc1: <Realtek (0x0668) HDA CODEC> at cad 0 on hdac1
hdaa1: <Realtek (0x0668) Audio Function Group> at nid 1 on hdacc1
pcm1: <Realtek (0x0668) (Internal Analog)> at nid 20 and 18 on hdaa1
pcm2: <Realtek (0x0668) (Right Analog)> at nid 21 and 24 on hdaa1
pcm3: <Realtek (0x0668) (Right Digital)> at nid 30 on hdaa1
Anyway, I can see that changing the output manually is a lot easier way around :D . I'm ok with that. It's just that I don't know many people to whom I could recommend FreeBSD because of these details (manual sound output change, weird issues about wifi). Most of them expect these things to "just work" (well, me included until recently). I take moving from Linux to FreeBSD as sort of a personal challenge and I'm enjoying it :) but it's a pity that I can't bring more people with me. I realize that FreeBSD doesn't specifically target desktop users but if these little annoyances weren't there (or were easier to deal with) it could attract much bigger user base (or so I believe).

EDIT: After re-reading my post I noticed that everything I need really is in dmesg() output. Many thanks to you @ondra_knezour. I'll test it soon and past the results here.
 
Last edited by a moderator:
Re: Automaticaly switch audio output when speakers are conne

Ok,
it took me like hundred of restarts (I mean literally) until I finally came to an understanding what is required from me. I'll save your time and won't past all the misconfigurations and their funny outcomes here, I'll just past the working configuration of device.hints():
Code:
hint.hdaa.1.nid20.config="as=1 seq=0"
hint.hdaa.1.nid21.config="as=1 seq=15 device=Headphones"
It's that easy. I almost don't believe it.

Thank you so much for your advices guys, I greatly appreciate it.
 
Back
Top