[alsa-devel] Via VT2020: issues with kernel 2.6.38.{2, 3} (alsa 1.0.23) - working with 2.6.33.2 (alsa 1.0.21)
Hello, First of all let me apologize if I'm not fulfilling any requirements for this list, and for any errors in my English. I've sent a mail with same subject and content to this list as a non-subscriber on April, 26, but perhaps that's gone lost, or perhaps is still under moderation or didn't pass it, so I'm resending this from a different address as a subscriber. So, please, ignore my previous mail if it came out from moderation.
As per subject, I'm experiencing problems with my motherboard built-in audio device (an Asrock with ATI SB8xx), embedding a Via VT2020 codec (I haven't tested the ATI HDMI part in same conditions).
The card is recognized 'about' correctly (later in this mail something about dmesg and other issues), and stuff in /proc/asound seems correct, also I have no apparent problem with /dev special files, but I get no sound after having installed kernel 2.6.38.2 and updated to version 2.6.38.3 (both compiled from source); no mixer seems to work (later specific errors), but everything still works with older kernel 2.6.33.2 I've kept in my system (built with the same build environment). Since I'm using the very same userspace environment in both cases, I deem it to be a driver(s) related issue more likely; though, I've updated my alsa-lib and -utils to latest versions (were such when I downloaded sources - alsa-lib 1.0.24.1 & alsa-utils 1.0.24.2) and still get the very same results.
But let me go into more details. Here is an excerpt from dmesg called with kernel 2.6.33.2 (sound works, but I'm just using headphone jack, so I can't tell about anything related with later issue with smart5.1 and hda I've seen in list archives):
[...] HDA Intel 0000:00:14.2: PCI INT A -> GSI 16 (level, low) -> IRQ 16 HDA Intel 0000:01:05.1: PCI INT B -> GSI 19 (level, low) -> IRQ 19 HDA Intel 0000:01:05.1: irq 28 for MSI/MSI-X HDA Intel 0000:01:05.1: setting latency timer to 64 [...] ohci1394 0000:04:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16 ohci1394 0000:04:00.0: setting latency timer to 64 [...] ohci1394: fw-host0: OHCI-1394 1.1 (PCI): IRQ=[16] MMIO=[fe9ff800-fe9fffff] Max Packet=[2048] IR/IT contexts=[4/8] ieee1394: Host added: ID:BUS[0-00:1023] GUID[008f130043910900] [...] hda-intel: azx_get_response timeout, switching to polling mode: last cmd=0x000f0001 [...]
Notice last line is an harmless warning (sound works) and is there because msi seems to be enabled by default; by adding "options snd-hda-intel enable_msi=0" to /etc/modprobe.d/alsa-base.conf both the warning and any reference to MSI/MSI-X disappear; same effect with pci=nomsi on command line (this time affecting other drivers, such as r8169). VT2020 is part of device 0000:00:14.2 sharing IRQ 16 with ohci1394; device 0000:01:05.1 is ATI HDMI, while device 0000:05.0 should be embedded radeon vga (bridged together according with lspci -t with 0000:00:01.0 on top); for each bridge I can find with lspci -t corresponding msi_bus file in sys filesystem (in /sys/bus/pci/devices/*) is always 1, regardless of any boot command (this with kernel 2.6.33.2).
Now an excerpt from dmesg in kernel 2.6.38.3:
[...] HDA Intel 0000:00:14.2: PCI INT A -> GSI 16 (level, low) -> IRQ 16 hda-codec: no NID for mapping control Independent HP:0:0 HDA Intel 0000:01:05.1: PCI INT B -> GSI 19 (level, low) -> IRQ 19 HDA Intel 0000:01:05.1: setting latency timer to 64 [...] r8169 0000:03:00.0: irq 43 for MSI/MSI-X [...] firewire_ohci 0000:04:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16 firewire_ohci 0000:04:00.0: setting latency timer to 64 [...] firewire_ohci: Added fw-ohci device 0000:04:00.0, OHCI v1.10, 4 IR + 8 IT contexts, quirks 0x11 firewire_core: created device fw0: GUID 008f130043910900, S400 [...]
Now firewire_ohci replaces ohci1394, again sharing IRQ 16 with hda-intel for vt2020. Line about r8169 is just for reference, since it gets a different irq for msi now. Similar behaviour for MSI: enabled/disabled with pci=nomsi (seems to be enabled by default without pci=msi) and msi_bus == 1 for bridges regardless of boot options, *but for bridge on top of ati hdmi device*: now msi seems to be disabled regardless of both 'enable_msi' option and pci=* boot command and corresponding bridge (device at bus 0000:00:01.0) holds a value of 0 for msi_bus...
Notice there are no more warnings about response timeouts, as it happened in older kernel after disabling msi (both globally and for alsa through alsa config options).
Notice also line "hda-codec: no NID for mapping control Independent HP:0:0". That's because function
'snd_hda_get_connections' (patch_via.c)
called by
'via_hp_build'
returns 3 ( test for 'nums <= 1' fails and the function doesn't return), but function
'side_mute_channel',
called to init knew->subdevice when 'registering' via_hp_mixer[1], returns 0 (default value) and so condition 'if(nid > 0)', in function
'snd_hda_add_nid' (hda_codec.c),
is not met and the error is triggered (by the way, param nid is of type hda_nid_t which in turn is an unsigned integer (u16), so, should that be 'if(nid != 0)' instead? just to avoid the risk of giving the impression that negative values are possible but mistaken (hda_nid_t is defined elsewhere). Also: param @nid, in function comment/documentation is defined as optional, but it doesn't seem to be). Incidentally, in /proc/asound/card0/codec#0 node 0x35 looks much like node 0x34 (with both older and newer kernel; posting excerpt for kernel 2.6.38.3):
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c* Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
(notice connections and wcaps similarity, if relevant at all)
Since I'm quite crazy, I've tried to modify 'side_mute_channel' to have it returning '0x35' for codec type 'VT1718S', but to no avail; I also tried to bypass 'snd_hda_add_nid', both avoiding 'via_hp_build' to clone via_hp_mixer[<something>] and/or modifying 'via_build_controls' and 'snd_hda_add_new_ctls' (hda_control.c) so that "Independent HP" ctls were handled by the latter (achieving this was just a matter of a pair of strcmp's to choose skipping the rest of an iteration or not), as I deem it was done in alsa 1.0.21 (embedded in kernel 2.6.33.2), but it didn't work (the only result I got this ways was to avoid that error message about nids in system logs).
Additional infos from userspace applications:
mplayer works fine with kernel 2.6.33.2 (again, only using one exit, I haven't tested all jacks combinations); called from cmdline (under X - but that's the same shutting X down) with default options ('mplayer <path/to/file>') it gives the following output (relevant excerpt, as I deem it, after codec choice, can provide more if needed):
socket(): Address family not supported by protocol AO: [pulse] Init failed: Connection refused Failed to initialize audio driver 'pulse' AO: [alsa] 48000Hz 2ch s16le (2 bytes per sample) Starting playback...
(notice I'm not using alsa-tools, such as pulse-audio; with the above invocation sound/video works)
running mplayer with option '-ao sdl' (using sdl audio, same file) I get the following output:
[AO SDL] Samplerate: 44100Hz Channels: Stereo Format s16le AO: [sdl] 44100Hz 2ch s16le (2 bytes per sample) Starting playback...
Again, sound works. In both cases, I can notice a change in /proc/asound/card0/codec#0 as follows:
In nodes 0x08, 0x09, 0x0a, 0x0e (all [Audio Output] nodes, first 3 with 'wcaps 0x41d: Stereo Amp-Out', last with 'wcaps 0x611: Stereo Digital'), the following line:
Converter: stream=0, channel=0
changes into:
Converter: stream=5, channel=0
With kernel 2.6.38.x I get the following:
running mplayer with no option, I get no sound and following output:
socket(): Address family not supported by protocol AO: [pulse] Init failed: Connection refused Failed to initialize audio driver 'pulse' [AO_ALSA] alsa-lib: confmisc.c:768:(parse_card) cannot find card '0' [AO_ALSA] alsa-lib: conf.c:4184:(_snd_config_evaluate) function snd_func_card_driver returned error: No such device [AO_ALSA] alsa-lib: confmisc.c:392:(snd_func_concat) error evaluating strings [AO_ALSA] alsa-lib: conf.c:4184:(_snd_config_evaluate) function snd_func_concat returned error: No such device [AO_ALSA] alsa-lib: confmisc.c:1251:(snd_func_refer) error evaluating name [AO_ALSA] alsa-lib: conf.c:4184:(_snd_config_evaluate) function snd_func_refer returned error: No such device [AO_ALSA] alsa-lib: conf.c:4663:(snd_config_expand) Evaluate error: No such device [AO_ALSA] alsa-lib: pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM default [AO_ALSA] Playback open error: No such device Failed to initialize audio driver 'alsa' [AO SDL] Samplerate: 44100Hz Channels: Stereo Format s16le [AO SDL] using aalib audio driver. [AO SDL] Unable to open audio: No available audio device Failed to initialize audio driver 'sdl:aalib' Could not open/initialize audio device -> no sound. Audio: no sound
and nothing changes in codec#0 file; with option -ao sdl, instead:
[AO SDL] Samplerate: 44100Hz Channels: Stereo Format s16le ALSA lib confmisc.c:768:(parse_card) cannot find card '0' ALSA lib conf.c:4184:(_snd_config_evaluate) function snd_func_card_driver returned error: No such device ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings ALSA lib conf.c:4184:(_snd_config_evaluate) function snd_func_concat returned error: No such device ALSA lib confmisc.c:1251:(snd_func_refer) error evaluating name ALSA lib conf.c:4184:(_snd_config_evaluate) function snd_func_refer returned error: No such device ALSA lib conf.c:4663:(snd_config_expand) Evaluate error: No such device ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM default AO: [sdl] 44100Hz 2ch s16le (2 bytes per sample)
And sound works! Same changes as per (working) playback with kernel 33.2 (alsa 1.0.21) are noticeable in /proc/asound/card0/codec#0 in this case (that is, when getting sound with kernel 2.6.38.x); in addition, node 0x0c, now changes as well (again, '[Audio Output] wcaps 0x41d: Stereo Amp-Out.' and 'Converter: stream=5, channel=0')
Moreover: with kernel 38.2, 38.3 alsamixer fails telling about problems finding device:
cannot open mixer: No such device
And amixer says:
amixer: Mixer attach default error: No such device
But there's no problem with /dev stuff (and same devices works pretty fine with kernel 2.6.33.2) - aplay -l doesn't work as well:
aplay: device_list:240: no soundcards found...
With kernel 2.6.33.2, aplay -l says:
**** List of PLAYBACK Hardware Devices **** card 0: SB [HDA ATI SB], device 0: VT2020 Analog [VT2020 Analog] Subdevices: 2/2 Subdevice #0: subdevice #0 Subdevice #1: subdevice #1 card 0: SB [HDA ATI SB], device 1: VT2020 Digital [VT2020 Digital] Subdevices: 2/2 Subdevice #0: subdevice #0 Subdevice #1: subdevice #1 card 1: HDMI [HDA ATI HDMI], device 3: ATI HDMI [ATI HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0
A 'third party' mixer embedded in my distribution aborts by hitting a failed assertion in function
'snd_hctl_load' (hcontrol.c)
failing assertion being 'assert(hctl->count == 0)' - I've added a few simple lines above the assertion to print out some info on stderr, and got the following results:
In kernel 2.6.33.2:
hctl->count: 0 hctl->ctl: 134748144 (0x80817F0) hctl->ctl->name: hw:0
which seems reasonable - according to /proc/iomem address 0x80817F0 is in range 00100000-cf83ffff (system ram) and higher than kernel stuff subranges ( 01000000-012c3be7: Kernel code - 012c3be8-0141dadf : Kernel data - 01481000-014b1e03 : Kernel bss);
In kernel 2.6.38.2 & .38.3:
hctl->count: 1156 hctl->ctl: 5398 (0x1516) Segmentation fault
suggesting memory corruption (that's always the same address) - according to /proc/iomem address 0x1516 is in first range (0x0000-0xffff) which is reserved.
I thought (and hoped) that could have been somehow related to cached/noncached pages issue solved by commit c27b92295ab4c6b90b1cee94c4c9c1b4732e1c2e, but applying diff patch for kernel 2.6.38.3 didn't change anything. After that, I've read changelog for kermel 2.6.38.4 but such didn't seem to me to present related material, so I didn't updgrade.
I hope this post can help solving this issue and improving alsa infrastracture (I cannot easily go further). Best regards.
2011/5/8 alex dot baldacchino dot alsasub at gmail dot com < alex.baldacchino.alsasub@gmail.com>
Notice also line "hda-codec: no NID for mapping control Independent HP:0:0". That's because function
'snd_hda_get_connections' (patch_via.c)
called by
'via_hp_build'
returns 3 ( test for 'nums <= 1' fails and the function doesn't return), but function
'side_mute_channel',
called to init knew->subdevice when 'registering' via_hp_mixer[1], returns 0 (default value) and so condition 'if(nid > 0)', in function
'snd_hda_add_nid' (hda_codec.c),
is not met and the error is triggered (by the way, param nid is of type hda_nid_t which in turn is an unsigned integer (u16), so, should that be 'if(nid != 0)' instead? just to avoid the risk of giving the impression that negative values are possible but mistaken (hda_nid_t is defined elsewhere). Also: param @nid, in function comment/documentation is defined as optional, but it doesn't seem to be). Incidentally, in /proc/asound/card0/codec#0 node 0x35 looks much like node 0x34 (with both older and newer kernel; posting excerpt for kernel 2.6.38.3):
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c* Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
(notice connections and wcaps similarity, if relevant at all)
Since I'm quite crazy, I've tried to modify 'side_mute_channel' to have it returning '0x35' for codec type 'VT1718S', but to no avail; I also tried to bypass 'snd_hda_add_nid', both avoiding 'via_hp_build' to clone via_hp_mixer[<something>] and/or modifying 'via_build_controls' and 'snd_hda_add_new_ctls' (hda_control.c) so that "Independent HP" ctls were handled by the latter (achieving this was just a matter of a pair of strcmp's to choose skipping the rest of an iteration or not), as I deem it was done in alsa 1.0.21 (embedded in kernel 2.6.33.2), but it didn't work (the only result I got this ways was to avoid that error message about nids in system logs).
Try the snapshot tarballs or git at
http://www.kernel.org/pub/linux/kernel/people/tiwai/docs/HD-Audio.html
Post the output of alsa-info.sh
What is the model of your computer (desktop/notebook) ?
How many audio jacks ?
https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/729659
It seem that vt2020 is 10 channels HDA with 5 [Audio Output] 0x8, 0x9, 0xa, 0xb and 0xc
Hello,
Thanks for your answer.
2011/5/8 Raymond Yau superquad.vortex2@gmail.com:
2011/5/8 alex dot baldacchino dot alsasub at gmail dot com < alex.baldacchino.alsasub@gmail.com>
[...]
Try the snapshot tarballs or git at
http://www.kernel.org/pub/linux/kernel/people/tiwai/docs/HD-Audio.html
Sorry, I've never build modules out of 'regular' kernel build process before, so I'd have a few questions. I'm using a tarball kernel source for kernel 2.6.38.2 taken from kernel.org, patched with some stuff required by my distro (therein aufs) and incremented to version 2.6.38.3 with the incremental patch taken, again, from kernel.org; I have no git version of the kernel to pull the alsa git snapshot over, and am not using a 'real' broadband connection at the moment, so I'd prefer not to download a full git source. For accomplishing your request, I've downloaded tarball alsa-driver-20110508.tar.bz2 from the ftp pointed to within the document linked above
Now my questions. In file 'SUPPORTED_KERNELS' I can read the following:
"The alsa-drivers in this package are designed for the following kernels:
- Vanilla 2.6.29 or earlier - Vanilla 2.4.31 or earlier - Vanilla 2.2.26 or earlier
It's not guaranteed that they work with any newer version than above or modified kernels by distributors."
Is it a harmless warning, or should I upgrade my kernel to version 2.6.38.4 or 38.5 and test the embedded alsa version (more recent than current one I'm using) instead?
I've modified, through menuconfig ( CONFIG_LOCALVERSION ), my kernel version string, so I can modify configuration at whim and keep different flavors of the same kernel version (though I'm using just one flavor for k 2.6.38.3); moreover, kernel source path doesn't match the exact 'name' of the kernel (as named in /lib/modules/<version>) and is located out of /usr/src, though actual source path is symlinked from within kernel install dir as standard 'source' subdir (pointing to <path/to/linux-2.6.33.2>). Hence, for what I've understood from file 'INSTALL' in ALSA snapshot tarball, kernel version and source tree should be easily identified by configure script, however, in case there is a risk that ALSA snapshot gets misconfigured I prefer to ask if I'd better to explicitly pass in --with-kernel and --with-build options.
But my main concern is about overall configuration. For better comparison, I'd wish to use the very same sound configuration I've used in kernel build process, but that's unclear to me if configure script for ALSA snapshot will retrieve and use it, or if the script can just use configuration options passed in/default values (as a 'regular' configure script).
Lastly, do I need to enable debug? (that is, is it required for better alsa-info output?)
For now, below I'm posting alsa-info.sh output for current configuration and for kernel 2.6.33.2 (with working sound), hoping this can help for comparison.
Post the output of alsa-info.sh
What is the model of your computer (desktop/notebook) ?
Sorry I didn't make it more clear in my previous post. Mine is a home-build desktop with an Asrock motherboard (I don't know of any notebook with asrock MoBo), model '890GX Extreme3', with integrated graphics (Radeon HD4290) and audio (via vt2020 codec and ati hdmi), NB AMD 890GX, SB850; CPU is a Phenom II X4 (kernel 2.6.38.3 is configured with amd specific optimizations while retaining x86 compatibility code; kernel 2.6.33.2 has no cpu-related optimization enabled; both are 32 bit); 4 GB ddr3 memory; no expansion cards.
If more details are needed, I'll write full specs.
How many audio jacks ?
Rear panel: 5 jacks for 7.1 channels audio + 1 Optical SPDIF OUT port On board: front panel audio header for ac97/hd audio (connectors for mic, left, right - I'm not sure if that's for supporting 2 independent mono jacks, one stereo (headset) jack or both cases, I don't know neither ac97, nor hd audio specifications) + header for 1 hdmi_spdif out (to be connected to a discrete vga with hdmi capabilities)
https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/729659
It seem that vt2020 is 10 channels HDA with 5 [Audio Output] 0x8, 0x9, 0xa, 0xb and 0xc _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
__________________________________________________ OUTPUT FOR ALSA-INFO.SH -- K 2.6.38.3 - ALSA 1.0.23:
http://www.pastebin.ca/2055424
__________________________________________________ OUTPUT FOR ALSA-INFO.SH -- K2.6.33.2 - ALSA 1.0.21:
2011/5/9 alex dot baldacchino dot alsasub at gmail dot com < alex.baldacchino.alsasub@gmail.com>
you have to ask the distribution maintainer how to test the latest alsa-driver without upgrading the kernel.
it look like the driver is not installed correctly
!!Aplay/Arecord output !!------------
APLAY
aplay: device_list:240: no soundcards found...
ARECORD
arecord: device_list:240: no soundcards found...
!!Amixer output !!-------------
!!-------Mixer controls for card 0 [SB]
Invalid card number. Usage: amixer <options> [command]
Most likely you will need this patch
cb34c207af4944e9c93e2b462e351430f15daad6
so that the driver do not create "smart5.1" control since blue jack may need to retask as side according to the user manual
ALSA: hda - VIA: Fix Smart5.1 isn't useful for 6 audio jacks motherboard.
Lastly, do I need to enable debug? (that is, is it required for better alsa-info output?)
The driver print debug messages in system log , you are able to know which [Audio Output] is used when switch "Independent HP" on/off or retask blue jack as output
For now, below I'm posting alsa-info.sh output for current configuration and for kernel 2.6.33.2 (with working sound), hoping this can help for comparison.
Post the output of alsa-info.sh
What is the model of your computer (desktop/notebook) ?
Mine is a home-build desktop with an Asrock motherboard (I don't know of any notebook with asrock MoBo), model '890GX Extreme3', with integrated graphics (Radeon HD4290) and audio (via vt2020 codec and ati hdmi), NB AMD 890GX, SB850;
How many audio jacks ?
Rear panel: 5 jacks for 7.1 channels audio + 1 Optical SPDIF OUT port On board: front panel audio header for ac97/hd audio (connectors for mic, left, right -
Refer to page 12 of 890GX Extreme3 's user manual
TABLE for Audio Output Connection
Blue jack is re-tasked for "Side" channel to support 8 channels
"hda-codec: no NID for mapping control Independent HP:0:0".
Node 0x28 HP is connected to 0x34 through 0x1b
[Audio Output] 0x0c has the "Headphone Volume" control
As "Line in" can only be connected to 0x0c
so the fix mainly depend on whether 0x0b can be used or not
if vt2020 is as same as vt1718s, you need to find a correct nid in the function side_mute_channel() for update_side_mute_status() which mute/unmute side channel when independent HP Is "ON"/"OFF"
Node 0x2a [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x00002334: IN OUT Detect Vref caps: HIZ 50 100 Pin Default 0x0181303e: [Jack] Line In at Ext Rear Conn = 1/8, Color = Blue DefAssociation = 0x3, Sequence = 0xe Pin-ctls: 0x20: IN VREF_HIZ Unsolicited: tag=04, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 2 0x09* 0x0c
send: NID=0x21, VERB=0x370(set_amp_gain_mute,I:LR#0), PARM=0x80 send: NID=0x21, VERB=0x371(set_amp_gain_mute,I:LR#1), PARM=0x80 send: NID=0x21, VERB=0x372(set_amp_gain_mute,I:LR#2), PARM=0x80 send: NID=0x21, VERB=0x373(set_amp_gain_mute,I:LR#3), PARM=0x80 send: NID=0x21, VERB=0x375(set_amp_gain_mute,I:LR#5), PARM=0x0 invalid amp index 5 (conns=5)
Node 0x21 only has 5 connections instead of 6
Seem no "Stereo Mix" , 0x28 is HP and only 0x2c, 0x2b and 0x29 are input sources and the other must be muted
node 0x2a "Line Playback Switch" have to be muted and write-protect whenever blue jack is retask
need to modify vt1718S_auto_create_analog_input_ctls()
Node 0x21 [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Control: name="Front Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=3, ofs=0 Control: name="Front Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=3, ofs=0 Control: name="Rear Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Rear Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Line Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Line Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x97 0x97] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 5 0x2c 0x2b 0x2a 0x29 0x28
I'm not sure if that's for supporting 2 independent mono jacks, one stereo (headset) jack or both cases,
http://www.intel.com/support/motherboards/desktop/sb/cs-020642.htm#multistre...
Multistreaming allows you to listen to two different audio sources on two different speaker sets. For example, you can listen to one audio source through the back panel speakers and a second audio source through front panel headphones or speakers.
In page 13,
To enable Multi-Streaming function, you need to connect a front panel audio cable to the front panel audio header,
I don't know neither ac97, nor hd audio specifications) + header for 1 hdmi_spdif out (to be connected to a discrete vga with hdmi capabilities)
http://www.intel.com/support/motherboards/desktop/sb/cs-020642.htm#standards *
How to Identify your Front Panel Audio Solution Codec
*You can also physically check the audio cable of the front panel audio solution. If there is a cable connected to Pin 4, you have an HD Audio module; if there is no cable to Pin 4, you have an AC97 module.
page 60 (BIOS setup)
Front Panel Select [Auto] or [Disabled] for the onboard HD Audio Front Panel.
Hello, It took me a while before I could post again here, sorry.
I've installed the snapshot tarball I had downloaded, with debug support enabled, result at following link; results are close to previous ones.
2011/5/10 Raymond Yau superquad.vortex2@gmail.com:
2011/5/9 alex dot baldacchino dot alsasub at gmail dot com < alex.baldacchino.alsasub@gmail.com>
you have to ask the distribution maintainer how to test the latest alsa-driver without upgrading the kernel.
It seems configure script for the snapshot has found correct source and installation paths, overwriting existing sound drivers, as expectable; I've left userspace configuration untouched (installed new modules with 'make install-modules' to leave alsa script in /etc/init.d as it was).
In my previous messages I forgot to mention my chassis has a front panel with mic and hp jacks; it is said to support both hd and ac'97 audio - it's got a multi-pin single connector labeled 'hd audio' with all available pins wired (fully fitting the MoBo header, and is actually inserted); from that one, another connector is derived, labeled 'ac97 audio', with a pair of pins missing and some other 'duplicated' (I'm not using it). I've made a few tests, one with front panel disabled in bios, one with front panel enabled in bios (bios option set to auto - please, note there can be an error in my MoBo manual, since only available options for the front panel are 'Auto' and 'Disabled', there's no 'Enabled' ) but physically unconnected. Results are at following addresses:
Front panel disabled in bios:
Front panel disconnected but enabled in bios:
Please, notice the following excerpts (perhaps it sounds normal at you, but I'm trying to understand how to interpret things at this stage):
With panel disabled in bios:
Node 0x0c [Audio Output] wcaps 0x41d: Stereo Amp-Out Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
( missing lines: Control: name="Headphone Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 )
Node 0x28 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x422140f0: [N/A] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0xf, Sequence = 0x0 Pin-ctls: 0x00: VREF_HIZ Unsolicited: tag=21, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 1 0x1b
( missing lines: Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 different 'Pin Default', different 'DefAssociation' )
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c*
( missing line: Control: name="Independent HP", index=0, device=0 )
/sys/class/sound/hwC0D0/init_pin_configs: 0x24 0x01014010 0x25 0x01011012 0x26 0x01016011 0x27 0x410120f0 0x28 0x422140f0 0x29 0x42a190f7 0x2a 0x0181303e 0x2b 0x01a19036 0x2c 0x593701f8 0x2d 0x074510f0 0x2e 0x474401f0 0x2f 0x47c411f0
( different pin configurations with respect to the normal case - the first link in this message - and the following case )
ALSA hda_intel.c:1457: Enable sync_write for AMD chipset ALSA hda_codec.c:4707: autoconfig: line_outs=3 (0x24/0x25/0x26/0x0/0x0) type:line ALSA hda_codec.c:4711: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4715: hp_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4716: mono: mono_out=0x0 ALSA hda_codec.c:4719: dig-out=0x2d/0x0 ALSA hda_codec.c:4720: inputs: ALSA hda_codec.c:4726:
( it seems there's no hp output, 0x28 is _not_ listed )
With front panel disconnected but enabled in bios:
Node 0x0c [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Headphone Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
( as if panel were connected )
Node 0x28 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x0221411f: [Jack] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0xf Misc = NO_PRESENCE Pin-ctls: 0xc0: OUT HP VREF_HIZ Unsolicited: tag=21, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 1 0x1b
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3
( again, as when panel is connected, but for line: Misc = NO_PRESENCE )
/sys/class/sound/hwC0D0/init_pin_configs: 0x24 0x01014010 0x25 0x01011012 0x26 0x01016011 0x27 0x410120f0 0x28 0x0221411f 0x29 0x02a19137 0x2a 0x0181303e 0x2b 0x01a19036 0x2c 0x593701f8 0x2d 0x074510f0 0x2e 0x474401f0 0x2f 0x47c411f0
ALSA hda_codec.c:4707: autoconfig: line_outs=3 (0x24/0x25/0x26/0x0/0x0) type:line ALSA hda_codec.c:4711: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4715: hp_outs=1 (0x28/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4716: mono: mono_out=0x0 ALSA hda_codec.c:4719: dig-out=0x2d/0x0 ALSA hda_codec.c:4720: inputs: ALSA hda_codec.c:4726:
It seems that node 0x28 represents the front panel line-out and connection 0x0c is not used by anyone else (possible? rigth to work this way? am I misunderstanding the log?). On the other hand, it is labeled as "[Jack] HP Out at Ext Front", so it was expectable to work this way (right?).
Now, I'm courious about node 0x24, which represents the rear green line-out (and is the only rear line-out involved in all output configurations, from 2 to 8 channels); in all cases it is presented the following way:
Node 0x24 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Front Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0001001c: OUT HP EAPD Detect EAPD 0x2: EAPD Pin Default 0x01014010: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0x0 Pin-ctls: 0x40: OUT Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 1 0x18
Node 0x18 [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x00 0x00] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 2 0x08 0x21
Node 0x08 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Front Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Device: name="VT2020 Analog", type="Audio", device=0 Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
0x08 is also listed as possible connection for node 0x034 and 0x035
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c* Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
Therefore, could 0x18 be a suitable return value for side_mute_channel() function? (though I'd suppose an 'Audio Selector' should be looked for instead of an 'Audio Mixer') How could I check that?
In other words, I need also to understand what are exactly the "Independent HP"s looked for and how they're enumerated, whether by counting all possible output configurations that could be involved in a Multi-Stream scenario (hence including rear channels) or just those ones which exist beside the 'main group' (the rear group of line-outs making up multichannel configurations).
In the latter case, are they always coupled? I'm asking because it seems to me that via_hp_build() assumes there are either exactly 2 Independent HP controls (when snd_hda_get_connections() returns a value greater than 1) or none (otherwise). Could there be just one such control instead?
it look like the driver is not installed correctly [...cut...]
All is possible... but I wonder how... All I've done is downloading the new kernel, patching it according to older kernels for my distro (nothing related to sound, just lowering DEFAULT_CONSOLE_LOGLEVEL from 7 to 3, adding a few printk's to usb-storage, additional vortex device ids, aufs), configuring it through 'make menuconfig' (using older kernel configuration as a hint), issuing 'make bzImage', issuing 'make modules', issuing 'make INSTALL_MOD_PATH=/some/path modules_install", copying modules in their final destination ( /lib/modules/<version> ), updating my initrd (which doesn't handle sound) and rebooting.... I've left sound configuration (userspace-side) untouched.
That worked with the older kernel I'm using (from my distro - it was yet configured and patched, but I've updated patches - such as aufs - tuned it a few times to create different flavours, build and installed it as above). Unless there's something only working for alsa 1.0.21 and causing problems with alsa 1.0.23 - alsa 1.0.24 in /etc/init.d/alsa, /etc/modprobe.d/* files (I have no .asoundrc), drivers installation shouldn't be the problem, AFAICT...
Most likely you will need this patch
cb34c207af4944e9c93e2b462e351430f15daad6
so that the driver do not create "smart5.1" control since blue jack may need to retask as side according to the user manual
ALSA: hda - VIA: Fix Smart5.1 isn't useful for 6 audio jacks motherboard.
I guess that should be embedded in the snapshot I've installed... In file 'patch_via.c', function 'via_smart51_build' checks for line_outs number before cloning smart5.1 controls; anyway, there's nothing connected to my blue jack at the moment.
Lastly, do I need to enable debug? (that is, is it required for better alsa-info output?)
The driver print debug messages in system log , you are able to know which [Audio Output] is used when switch "Independent HP" on/off or retask blue jack as output
Well, alsa-info.sh collects those messages related to sound, I was asking if people here wish to read them for a better understanding of the problem (I've enabled debug in the snapshot, so those lines are in my new alsa-info posts). Sorry I wasn't clear about my doubt.
For now, below I'm posting alsa-info.sh output for current configuration and for kernel 2.6.33.2 (with working sound), hoping this can help for comparison.
Post the output of alsa-info.sh
What is the model of your computer (desktop/notebook) ?
Mine is a home-build desktop with an Asrock motherboard (I don't know of any notebook with asrock MoBo), model '890GX Extreme3', with integrated graphics (Radeon HD4290) and audio (via vt2020 codec and ati hdmi), NB AMD 890GX, SB850;
How many audio jacks ?
Rear panel: 5 jacks for 7.1 channels audio + 1 Optical SPDIF OUT port On board: front panel audio header for ac97/hd audio (connectors for mic, left, right -
Refer to page 12 of 890GX Extreme3 's user manual
TABLE for Audio Output Connection
Blue jack is re-tasked for "Side" channel to support 8 channels
I was trying to count the max number of jacks my MoBo can support, regardless they're in the rear or front panel, present or not. I guess you were asking for rear ones only, sorry for my misunderstanding.
"hda-codec: no NID for mapping control Independent HP:0:0".
Node 0x28 HP is connected to 0x34 through 0x1b
[Audio Output] 0x0c has the "Headphone Volume" control
As "Line in" can only be connected to 0x0c
so the fix mainly depend on whether 0x0b can be used or not
How can I check that? (that is, 0x0b usability for the purpose?)
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c*
What does the asterisk mean? Is it to indicate the active/used connection?
It seems to me that
Node 0x29 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Front Mic Boost Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x02a19037: [Jack] Mic at Ext Front Conn = 1/8, Color = Pink DefAssociation = 0x3, Sequence = 0x7 Pin-ctls: 0x21: IN VREF_50 Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 1 0x1c
is connected through
Node 0x1c [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 2 0x35 0x21
to
Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
which uses
Node 0x0b [Audio Output] wcaps 0x41d: Stereo Amp-Out Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3
Am I wrong? Should it work differently?
if vt2020 is as same as vt1718s, you need to find a correct nid in the function side_mute_channel() for update_side_mute_status() which mute/unmute side channel when independent HP Is "ON"/"OFF"
Given actual implementation, those should be at least compatible to some extent; in case there were differences between nids in different 'flavours' of vt1718s ( for the sake of side_mute_channel(struct via_spec *spec) ), it should be possible to check spec->codec->vendor_id within the switch statement when spec->codec_type is VT1718S - the problem is finding the right nid
Node 0x2a [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x00002334: IN OUT Detect Vref caps: HIZ 50 100 Pin Default 0x0181303e: [Jack] Line In at Ext Rear Conn = 1/8, Color = Blue DefAssociation = 0x3, Sequence = 0xe Pin-ctls: 0x20: IN VREF_HIZ Unsolicited: tag=04, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 2 0x09* 0x0c
send: NID=0x21, VERB=0x370(set_amp_gain_mute,I:LR#0), PARM=0x80 send: NID=0x21, VERB=0x371(set_amp_gain_mute,I:LR#1), PARM=0x80 send: NID=0x21, VERB=0x372(set_amp_gain_mute,I:LR#2), PARM=0x80 send: NID=0x21, VERB=0x373(set_amp_gain_mute,I:LR#3), PARM=0x80 send: NID=0x21, VERB=0x375(set_amp_gain_mute,I:LR#5), PARM=0x0 invalid amp index 5 (conns=5)
How did you get these values?
Seem no "Stereo Mix" , 0x28 is HP and only 0x2c, 0x2b and 0x29 are input sources and the other must be muted
node 0x2a "Line Playback Switch" have to be muted and write-protect whenever blue jack is retask
need to modify vt1718S_auto_create_analog_input_ctls()
I have no idea how to do that, my understanding of the code is to limited for now. Perhaps it should be also considered if one needs to modify only vt1718S_auto_create_analog_input_ctls(), both this one and vt_auto_create_analog_input_ctls() or just the latter (but perhaps you just mean the former function should pass a different array to the latter one, and I'm misunderstanding they should also take care somehow of node 0x2a retasking, at least on creation)
Node 0x2c [Pin Complex] wcaps 0x400401: Stereo Pincap 0x00000020: IN Pin Default 0x593701f8: [N/A] CD at Int ATAPI Conn = Analog, Color = Unknown DefAssociation = 0xf, Sequence = 0x8 Misc = NO_PRESENCE Pin-ctls: 0x00: Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
What should this be? It doesn't seem to me there's any CD Audio connector in my motherboard. Is it supported by the codec anyway?
Regards
2011/5/17 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com
Hello, It took me a while before I could post again here, sorry.
I've installed the snapshot tarball I had downloaded, with debug support enabled, result at following link; results are close to previous ones.
2011/5/10 Raymond Yau superquad.vortex2@gmail.com:
2011/5/9 alex dot baldacchino dot alsasub at gmail dot com < alex.baldacchino.alsasub@gmail.com>
you have to ask the distribution maintainer how to test the latest alsa-driver without upgrading the kernel.
It seems configure script for the snapshot has found correct source and installation paths, overwriting existing sound drivers, as expectable; I've left userspace configuration untouched (installed new modules with 'make install-modules' to leave alsa script in /etc/init.d as it was).
!!Aplay/Arecord output !!------------
APLAY
aplay: device_list:240: no soundcards found...
ARECORD
arecord: device_list:240: no soundcards found...
!!Amixer output !!-------------
!!-------Mixer controls for card 0 [SB]
Invalid card number. Usage: amixer <options> [command]
You may need the expert to tell you what 's wrong since you need amixer to change the controls and aplay/arecord to perform test
In my previous messages I forgot to mention my chassis has a front panel with mic and hp jacks; it is said to support both hd and ac'97 audio - it's got a multi-pin single connector labeled 'hd audio' with all available pins wired (fully fitting the MoBo header, and is actually inserted); from that one, another connector is derived, labeled 'ac97 audio', with a pair of pins missing and some other 'duplicated' (I'm not using it). I've made a few tests, one with front panel disabled in bios, one with front panel enabled in bios (bios option set to auto - please, note there can be an error in my MoBo manual, since only available options for the front panel are 'Auto' and 'Disabled', there's no 'Enabled' ) but physically unconnected. Results are at following addresses:
Front panel disabled in bios:
With panel disabled in bios:
Node 0x28 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x422140f0: [N/A] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0xf, Sequence = 0x0 Pin-ctls: 0x00: VREF_HIZ Unsolicited: tag=21, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 1 0x1b
ALSA hda_intel.c:1457: Enable sync_write for AMD chipset ALSA hda_codec.c:4707: autoconfig: line_outs=3 (0x24/0x25/0x26/0x0/0x0) type:line ALSA hda_codec.c:4711: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4715: hp_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4716: mono: mono_out=0x0 ALSA hda_codec.c:4719: dig-out=0x2d/0x0 ALSA hda_codec.c:4720: inputs: ALSA hda_codec.c:4726:
( it seems there's no hp output, 0x28 is _not_ listed )
Some part of the code in the driver seem expect HP jack always present but this is not true any more As someone mention in the bug report that his small desktop (used as media center) does not even has the front audio panel,
using hda-emu and your codec info
send: NID=0x0, VERB=0xf00(get_parameters), PARM=0xc(pin_cap) receive: 0x0 send: NID=0x0, VERB=0xf09(get_pin_sense), PARM=0x0 Invalid pin node receive: 0x0
The driver should not create "Independent HP" switch when there is no hp jack
There shold be only one subdevice when there is no "Independent HP" switch
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = + ( snd_hda_find_mixer_ctl(codec, "Independent HP") ? 2 : 1);
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
Front panel disconnected but enabled in bios:
Node 0x28 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x0221411f: [Jack] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0xf Misc = NO_PRESENCE Pin-ctls: 0xc0: OUT HP VREF_HIZ Unsolicited: tag=21, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 1 0x1b
Misc=NO_PRESENCE mean the external circuitry is not capable of supporting the functionality
Misc[3:0] is a bit field used to indicate other information about the jack. Currently, only bit 0 is defined. If bit 0 is set, it indicates that the jack has no presence detect capability, so even if a Pin Complex indicates that the codec hardware supports the presence detect functionality on the jack, the external circuitry is not capable of supporting the functionality.
( again, as when panel is connected, but for line: Misc = NO_PRESENCE )
ALSA hda_codec.c:4707: autoconfig: line_outs=3 (0x24/0x25/0x26/0x0/0x0) type:line ALSA hda_codec.c:4711: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4715: hp_outs=1 (0x28/0x0/0x0/0x0/0x0) ALSA hda_codec.c:4716: mono: mono_out=0x0 ALSA hda_codec.c:4719: dig-out=0x2d/0x0 ALSA hda_codec.c:4720: inputs: ALSA hda_codec.c:4726:
It seems that node 0x28 represents the front panel line-out and connection 0x0c is not used by anyone else (possible? rigth to work this way? am I misunderstanding the log?). On the other hand, it is labeled as "[Jack] HP Out at Ext Front", so it was expectable to work this way (right?).
Do you mean the BIOS is able to differentiate HD front panel and AC97 Front panel without user to setup ?
I think those first generation HDA codecs are AC97 compatible
Now, I'm courious about node 0x24, which represents the rear green line-out (and is the only rear line-out involved in all output configurations, from 2 to 8 channels); in all cases it is presented the following way:
Node 0x24 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Front Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0001001c: OUT HP EAPD Detect EAPD 0x2: EAPD Pin Default 0x01014010: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0x0 Pin-ctls: 0x40: OUT Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 1 0x18
Node 0x18 [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x00 0x00] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 2 0x08 0x21
Node 0x08 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Front Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Device: name="VT2020 Analog", type="Audio", device=0 Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
0x08 is also listed as possible connection for node 0x034 and 0x035
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c* Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
Therefore, could 0x18 be a suitable return value for side_mute_channel() function? (though I'd suppose an 'Audio Selector' should be looked for instead of an 'Audio Mixer') How could I check that?
In other words, I need also to understand what are exactly the "Independent HP"s looked for and how they're enumerated, whether by counting all possible output configurations that could be involved in a Multi-Stream scenario (hence including rear channels) or just those ones which exist beside the 'main group' (the rear group of line-outs making up multichannel configurations).
The usage of those [Audio Output] are defined in vt1718S_auto_create_multi_out_ctls()
In the latter case, are they always coupled? I'm asking because it seems to me that via_hp_build() assumes there are either exactly 2 Independent HP controls (when snd_hda_get_connections() returns a value greater than 1) or none (otherwise). Could there be just one such control instead?
it look like the driver is not installed correctly [...cut...]
All is possible... but I wonder how... All I've done is downloading the new kernel, patching it according to older kernels for my distro (nothing related to sound, just lowering DEFAULT_CONSOLE_LOGLEVEL from 7 to 3, adding a few printk's to usb-storage, additional vortex device ids, aufs), configuring it through 'make menuconfig' (using older kernel configuration as a hint), issuing 'make bzImage', issuing 'make modules', issuing 'make INSTALL_MOD_PATH=/some/path modules_install", copying modules in their final destination ( /lib/modules/<version> ), updating my initrd (which doesn't handle sound) and rebooting.... I've left sound configuration (userspace-side) untouched.
That worked with the older kernel I'm using (from my distro - it was yet configured and patched, but I've updated patches - such as aufs - tuned it a few times to create different flavours, build and installed it as above). Unless there's something only working for alsa 1.0.21 and causing problems with alsa 1.0.23 - alsa 1.0.24 in /etc/init.d/alsa, /etc/modprobe.d/* files (I have no .asoundrc), drivers installation shouldn't be the problem, AFAICT...
Most likely you will need this patch
cb34c207af4944e9c93e2b462e351430f15daad6
so that the driver do not create "smart5.1" control since blue jack may need to retask as side according to the user manual
ALSA: hda - VIA: Fix Smart5.1 isn't useful for 6 audio jacks motherboard.
I guess that should be embedded in the snapshot I've installed... In file 'patch_via.c', function 'via_smart51_build' checks for line_outs number before cloning smart5.1 controls; anyway, there's nothing connected to my blue jack at the moment.
Lastly, do I need to enable debug? (that is, is it required for better alsa-info output?)
The driver print debug messages in system log , you are able to know which [Audio Output] is used when switch "Independent HP" on/off or retask blue jack as output
Well, alsa-info.sh collects those messages related to sound, I was asking if people here wish to read them for a better understanding of the problem (I've enabled debug in the snapshot, so those lines are in my new alsa-info posts). Sorry I wasn't clear about my doubt.
For now, below I'm posting alsa-info.sh output for current configuration and for kernel 2.6.33.2 (with working sound), hoping this can help for comparison.
Post the output of alsa-info.sh
What is the model of your computer (desktop/notebook) ?
Mine is a home-build desktop with an Asrock motherboard (I don't know of any notebook with asrock MoBo), model '890GX Extreme3', with integrated graphics (Radeon HD4290) and audio (via vt2020 codec and ati hdmi), NB AMD 890GX, SB850;
How many audio jacks ?
Rear panel: 5 jacks for 7.1 channels audio + 1 Optical SPDIF OUT port On board: front panel audio header for ac97/hd audio (connectors for mic, left, right -
Refer to page 12 of 890GX Extreme3 's user manual
TABLE for Audio Output Connection
Blue jack is re-tasked for "Side" channel to support 8 channels
I was trying to count the max number of jacks my MoBo can support, regardless they're in the rear or front panel, present or not. I guess you were asking for rear ones only, sorry for my misunderstanding.
"hda-codec: no NID for mapping control Independent HP:0:0".
Node 0x28 HP is connected to 0x34 through 0x1b
[Audio Output] 0x0c has the "Headphone Volume" control
As "Line in" can only be connected to 0x0c
so the fix mainly depend on whether 0x0b can be used or not
How can I check that? (that is, 0x0b usability for the purpose?)
static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) { char name[32]; static const char * const chname[4] = { "Front", "Surround", "C/LFE", "Side" }; hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb}; hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27};
the current driver only support 6 channels since it cannot find the grey jack at node 0x27
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
The current driver seem work with 6 jacks motherboard and need fix to work with 5 jacks motherboard
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b 0x0c*
What does the asterisk mean? Is it to indicate the active/used connection?
It seems to me that
Node 0x29 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Front Mic Boost Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x02a19037: [Jack] Mic at Ext Front Conn = 1/8, Color = Pink DefAssociation = 0x3, Sequence = 0x7 Pin-ctls: 0x21: IN VREF_50 Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 1 0x1c
is connected through
Node 0x1c [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 2 0x35 0x21
to
Node 0x35 [Audio Selector] wcaps 0x300501: Stereo Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08 0x0b* 0x0c
which uses
Node 0x0b [Audio Output] wcaps 0x41d: Stereo Amp-Out Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3
Am I wrong? Should it work differently?
Take a look at via_independent_get() and via_independent_put()
pinsel determine the connection of [Audio Selector] to [Audio Output] 0x08 , 0x0b and 0x0c
so it depend on using 0x0b or 0x0c as [Audio Output] for headphone
if vt2020 is as same as vt1718s, you need to find a correct nid in the function side_mute_channel() for update_side_mute_status() which mute/unmute side channel when independent HP Is "ON"/"OFF"
it seem that vt1718s does not need to update_side_mute_status if there is a grey jack
http://git.alsa-project.org/?p=alsa-kernel.git;a=commit;h=4d02d1b638af580ae3...
static const struct snd_kcontrol_new via_hp_mixer[2] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Independent HP", .info = via_independent_hp_info, .get = via_independent_hp_get, .put = via_independent_hp_put, }, { .iface = NID_MAPPING, .name = "Independent HP", }, };
Given actual implementation, those should be at least compatible to some extent; in case there were differences between nids in different 'flavours' of vt1718s ( for the sake of side_mute_channel(struct via_spec *spec) ), it should be possible to check spec->codec->vendor_id within the switch statement when spec->codec_type is VT1718S - the problem is finding the right nid
https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/772638
There is codec info of vt1718s on ASRock H55M Pro
comparing the nodes and topology with those of vt1718s
vt2020 has
Node 0x13 [Audio Input] wcaps 0x100711: Stereo Digital Node 0x22 [Beep Generator Widget] wcaps 0x70040c: Mono Amp-Out Node 0x2f [Pin Complex] wcaps 0x400601: Stereo Digital
1) grey jack at 0x27 is connected to 0x0b through 0x1a and HP is connected to 0x0c through 0x1b
what the driver need is a "channel mode" switch from 6 to 8 which configure 0x2a as output/input , and change max_channels between 6 and 8
2) without grey jack ,
note there can be an error in my MoBo manual,
There are two choice a) 0x2a is really can be retask as output and connected to 0x0c so HP may need to connect to 0x0b
b) HP is retasked as Side
http://www.viaarena.com/forums/showthread.php?t=41015
Refer to administrator 's answer
The Headphone Configuration Panel is shown in Figure 18. There are two headphone configurations that can be chosen: “Independent Headphone” or “Redirected Headphone”. The “Independent Headphone” feature enables the user to play separate music on the headphone and speaker. For example, the user can use a multi-channel device (such as 5.1 surround sound) to watch a movie while simultaneously using the independent headphone feature to make phone calls through a VoIP Internet phone.
The “Redirected Headphone” feature enables the user to hear the same audio that is being channeled to the front speakers. In this mode, once the headphone has been inserted the audio will be redirected from the speakers to the headphone. Please note that the “Independent Headphone” function requires two channels. Therefore, only six channels will be available if “Independent Headphone” is being used.
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
When Independent HP is off, (it is similar to Redirected Headphone) when automute is not enabled
send: NID=0x21, VERB=0x370(set_amp_gain_mute,I:LR#0), PARM=0x80 send: NID=0x21, VERB=0x371(set_amp_gain_mute,I:LR#1), PARM=0x80 send: NID=0x21, VERB=0x372(set_amp_gain_mute,I:LR#2), PARM=0x80 send: NID=0x21, VERB=0x373(set_amp_gain_mute,I:LR#3), PARM=0x80 send: NID=0x21, VERB=0x375(set_amp_gain_mute,I:LR#5), PARM=0x0 invalid amp index 5 (conns=5)
How did you get these values?
hda-emu show this error since 0x21 only has 5 connections
ode 0x21 [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x97 0x97] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 5 0x2c 0x2b 0x2a 0x29 0x28
Fix seem to be
static const struct hda_verb vt1718S_volume_init_verbs[] = {
/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
Seem no "Stereo Mix" , 0x28 is HP and only 0x2c, 0x2b and 0x29 are input sources and the other must be muted
node 0x2a "Line Playback Switch" have to be muted and write-protect whenever blue jack is retask
need to modify vt1718S_auto_create_analog_input_ctls()
I have no idea how to do that, my understanding of the code is to limited for now. Perhaps it should be also considered if one needs to modify only vt1718S_auto_create_analog_input_ctls(), both this one and vt_auto_create_analog_input_ctls() or just the latter (but perhaps you just mean the former function should pass a different array to the latter one, and I'm misunderstanding they should also take care somehow of node 0x2a retasking, at least on creation)
Can you record from blue jack ?
you should able to hear the input signal of blue jack at green jack when you unmute "Line Playback Volume"
Node 0x2c [Pin Complex] wcaps 0x400401: Stereo Pincap 0x00000020: IN Pin Default 0x593701f8: [N/A] CD at Int ATAPI Conn = Analog, Color = Unknown DefAssociation = 0xf, Sequence = 0x8 Misc = NO_PRESENCE Pin-ctls: 0x00: Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
What should this be? It doesn't seem to me there's any CD Audio connector in my motherboard. Is it supported by the codec anyway?
This mean that No physical connection for CD connector at the motherboard
Pin Default 0x593701f8
Bit 31:30 Port connectiviy
00b The Port Complex is connected to a jack (1/8", ATAPI, etc.). 01b No physical connection for Port. 10b A fixed function device (integrated speaker, integrated mic, etc.) is attached. 11b Both a jack and an internal device are attached. The Information provided in all other fields refers to the integrated device. The PD pin will reflect the status of the jack; the user will need to be queried to figure out what it is.
2011/5/18 Raymond Yau superquad.vortex2@gmail.com:
2011/5/17 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com
Hello, It took me a while before I could post again here, sorry.
I've installed the snapshot tarball I had downloaded, with debug support enabled, result at following link; results are close to previous ones. [...] It seems configure script for the snapshot has found correct source and installation paths, overwriting existing sound drivers, as expectable; I've left userspace configuration untouched (installed new modules with 'make install-modules' to leave alsa script in /etc/init.d as it was).
!!Aplay/Arecord output !!------------
APLAY
aplay: device_list:240: no soundcards found...
ARECORD
arecord: device_list:240: no soundcards found...
!!Amixer output !!-------------
!!-------Mixer controls for card 0 [SB]
Invalid card number. Usage: amixer <options> [command]
You may need the expert to tell you what 's wrong since you need amixer to change the controls and aplay/arecord to perform test
As I wrote in my first mail, there's a mixer in my system failing an assertion in alsa-lib; starting from there I've investigated what was going on there in (by adding some fprintf to stderr to a few library functions) and have found a sort of inconsistency across /dev/snd/* files minors, udev and the driver. Alsa-lib was using files in /dev/snd, which are statically created with minors that work in kernel 2.6.33.2 + alsa driver 1.0.21, but seems to be unusable for driver version 1.0.23 - 1.0.24. At the same time, udev created sound related stuff in /dev (which weren't used), with the very same major/minor as those ones in /dev/snd in k .33 + alsa 1.0.21, but different minors with a newer alsa driver (e.g. I get /dev/controlC0 with minor 6 (by udev) vs /dev/snd/controlC0 (statically existing) with minor 0, /dev/controlC1 with minor 9 vs /dev/snd/controlC1 with minor 32 and so on). Changing some macros in alsa lib, such as SND_FILE_CONTROL in cards.c, so that files in /dev where used seemed to solve, so I've rebuild alsa lib with option "--with-alsa-devdir=/dev" and now things seem to work... (please, note that's the same regardless of compiling the driver with or without support for dynamic minors, actually it works without dynamic minors using udev created files) alsa-info output at following link:
As an aside, I've noted there are different macros defined in different files (in alsa-lib source) to access the same resource. For instance, in file cards.c
#define SND_FILE_CONTROL ALSA_DEVICE_DIRECTORY "controlC%i"
and in file control_hw.c
#define SNDRV_FILE_CONTROL ALSA_DEVICE_DIRECTORY "controlC%i"
those are/can be used in the same 'context', I mean, at some point function _snd_ctl_hw_open() (in file control_hw.c) can call function snd_card_get_index() (in file cards.c) which uses function snd_card_load1() which uses SND_FILE_CONTROL; then (at last)_snd_ctl_hw_open() calls snd_ctl_hw_open() (same file) which uses SNDRV_FILE_CONTROL, but then snd_ctl_hw_open() can call snd_card_load (cards.c) and again snd_card_load1(). It might look a bit complicated (and somehow duplicated, but both _snd_ctl_hw_open() and snd_ctl_hw_open() are interface functions and could be eventually called independently), but I understand one may need to open a device ro and call an ioctl to get info about it before (re-)opening it rw (though I think functions in cards.c could avoid calling both snd_ctl_hw_open() and snd_ctl_card_info() with a simple change to snd_card_load2(), but that's another story). Anyway, the overall mechanism requires consistency between macros used to identify a control's path, so, perhaps, using just one and moving it into a (local, non-interface) header could improve maintainability a bit, eventually (just a little consideration).
Moreover, it looks like there's a bug in snd_ctl_hw_open() (but it could have been fixed and I could have missed it - just using the stable source I got a while ago for lib 1.0.24.1). In the end it executes the following block - I've added a comment where I think something else should be done:
err = snd_ctl_new(&ctl, SND_CTL_TYPE_HW, name); if (err < 0) { close(fd); free(hw); /* COMMENT ADDED BY ME */ /* should return -ENOMEM (that is err) ?*/ } ctl->ops = &snd_ctl_hw_ops; ctl->private_data = hw; ctl->poll_fd = fd; *handle = ctl; return 0;
If snd_ctl_new() failed, variable ctl would rest uninitialized and a random memory area would be overwritten by successive assignments to dereferenced offsets of ctl.
For the rest, I need some more learning of the driver and architecture insights. For the moment, I can tell the following.
First of all, I was misinterpreting entries in a connection list as outputs instead of inputs (as per hd audio specs), so I was a bit confused on what widget was driving what widget.
I've not applied the lines you were suggesting, because I'm still trying to understand how things work and how would work after any change (and have been more focused on solving driver installation issues).
Front panel disconnected but enabled in bios:
[..]
Misc=NO_PRESENCE mean the external circuitry is not capable of supporting the functionality
Misc[3:0] is a bit field used to indicate other information about the jack. Currently, only bit 0 is defined. If bit 0 is set, it indicates that the jack has no presence detect capability, so even if a Pin Complex indicates that the codec hardware supports the presence detect functionality on the jack, the external circuitry is not capable of supporting the functionality.
That's meaningful. Since the panel wasn't connected to the motherboard, just enabled in bios, the driver must have checked what signals came from that path and got none. It seems it worked as it should be supposed to.
Do you mean the BIOS is able to differentiate HD front panel and AC97 Front panel without user to setup ?
I think those first generation HDA codecs are AC97 compatible
My BIOS has only two options for the front panel: [Auto] and [Disabled], thus it should be capable of autodetection (though, the manual would suggest there should be a third option [Enabled] to set the front panel up as AC97, but there's no such option).
if vt2020 is as same as vt1718s, you need to find a correct nid in the function side_mute_channel() for update_side_mute_status() which mute/unmute side channel when independent HP Is "ON"/"OFF"
it seem that vt1718s does not need to update_side_mute_status if there is a grey jack
http://git.alsa-project.org/?p=alsa-kernel.git;a=commit;h=4d02d1b638af580ae3...
static const struct snd_kcontrol_new via_hp_mixer[2] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Independent HP", .info = via_independent_hp_info, .get = via_independent_hp_get, .put = via_independent_hp_put, }, { .iface = NID_MAPPING, .name = "Independent HP", }, };
Must these controls be always coupled? Is it a specification constraint? What if via_hp_build() didn't execute
knew = via_clone_control(spec, &via_hp_mixer[1]);
when side_mute_status() returned '0' ?
Given actual implementation, those should be at least compatible to some extent; in case there were differences between nids in different 'flavours' of vt1718s ( for the sake of side_mute_channel(struct via_spec *spec) ), it should be possible to check spec->codec->vendor_id within the switch statement when spec->codec_type is VT1718S - the problem is finding the right nid
https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/772638
There is codec info of vt1718s on ASRock H55M Pro
comparing the nodes and topology with those of vt1718s
vt2020 has
Node 0x13 [Audio Input] wcaps 0x100711: Stereo Digital Node 0x22 [Beep Generator Widget] wcaps 0x70040c: Mono Amp-Out Node 0x2f [Pin Complex] wcaps 0x400601: Stereo Digital
- grey jack at 0x27 is connected to 0x0b through 0x1a and HP is
connected to 0x0c through 0x1b
what the driver need is a "channel mode" switch from 6 to 8 which configure 0x2a as output/input , and change max_channels between 6 and 8
- without grey jack ,
note there can be an error in my MoBo manual,
There are two choice a) 0x2a is really can be retask as output and connected to 0x0c so HP may need to connect to 0x0b
b) HP is retasked as Side
I haven't got an 8-channel system to test it; according to the manual, line in should be used to create an 8 channel setup. As I understand it, line-in (blue jack) should be a replacement for the gray jack when retasked.
http://www.viaarena.com/forums/showthread.php?t=41015
Refer to administrator 's answer
The Headphone Configuration Panel is shown in Figure 18. There are two headphone configurations that can be chosen: “Independent Headphone” or “Redirected Headphone”. The “Independent Headphone” feature enables the user to play separate music on the headphone and speaker. For example, the user can use a multi-channel device (such as 5.1 surround sound) to watch a movie while simultaneously using the independent headphone feature to make phone calls through a VoIP Internet phone.
The “Redirected Headphone” feature enables the user to hear the same audio that is being channeled to the front speakers. In this mode, once the headphone has been inserted the audio will be redirected from the speakers to the headphone. Please note that the “Independent Headphone” function requires two channels. Therefore, only six channels will be available if “Independent Headphone” is being used.
The last part is interesting. If vt2020 works the same way, the 8-channel setup should disallow the "Independent HP" function, that is it should be automatically turned off and 0x28 should be either muted, or used as a 'duplicate' for 0x0c (same sound of blue jack) or 0x08 (same sound as rear green jack, as in 'redirected audio' ). If I'm not misunderstanding everything, of course.
BTW, 0x2a is connected to (gets input from) 0x09, which is labeled 'Surround Playback Volume' and is also an input for 0x25 ('Surround Playback Switch', black jack, rear speaker according to manual) throughout 0x19; 0x27 (missing gray jack) would be connected to 0x0b throughout 0x1a...
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
Tested: it works. I can get different streams out of rear (front playback) and front (hp) line out jacks (used mplayer on the 'default' rear channel(s) and aplay as above on the front panel)
When Independent HP is off, (it is similar to Redirected Headphone) when automute is not enabled
Turning off Independent HP I can notice the following change:
Node 0x34 [Audio Selector] wcaps 0x300501: Stereo Control: name="Independent HP", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 3 0x08* 0x0b 0x0c
Node 0x08 is connected to rear green jack, and I get same sound on both rear and front jacks
Seem no "Stereo Mix" , 0x28 is HP and only 0x2c, 0x2b and 0x29 are input sources and the other must be muted
node 0x2a "Line Playback Switch" have to be muted and write-protect whenever blue jack is retask
need to modify vt1718S_auto_create_analog_input_ctls()
I have no idea how to do that, my understanding of the code is to limited for now. Perhaps it should be also considered if one needs to modify only vt1718S_auto_create_analog_input_ctls(), both this one and vt_auto_create_analog_input_ctls() or just the latter (but perhaps you just mean the former function should pass a different array to the latter one, and I'm misunderstanding they should also take care somehow of node 0x2a retasking, at least on creation)
Can you record from blue jack ?
you should able to hear the input signal of blue jack at green jack when you unmute "Line Playback Volume"
I cannot test it properly at the moment. I've tried to use my headset's mic connected to blue jack, setting 'line' as first input source and executing 'arecord -vv -d 5 test.wav'. Playing the resulting file with "aplay -vv test.wav" showed a noisy and highly distorted, yet understandable (mono) sound (with all controls set to their max value); recording from rear mic jack, selecting both 'stereo mix' and 'rear mic' as input source created a more natural but still noisy sound (playing with the mixer solves the problem, but I needed top volumes to get sound from line-in without an external amplifier).
By the way, when I select 'Line' as input source with a mixer (selected both sources), I can notice the following changes:
Node 0x1e [Audio Selector] wcaps 0x300501: Stereo Control: name="Input Source", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 6 0x2c 0x2b 0x2a* 0x29 0x28 0x21 Node 0x1f [Audio Selector] wcaps 0x300501: Stereo Control: name="Input Source", index=1, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 6 0x2c 0x2b 0x2a* 0x29 0x28 0x21
Selecting 'stereo mixer' those are:
Node 0x1e [Audio Selector] wcaps 0x300501: Stereo Control: name="Input Source", index=0, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 6 0x2c 0x2b 0x2a 0x29 0x28 0x21* Node 0x1f [Audio Selector] wcaps 0x300501: Stereo Control: name="Input Source", index=1, device=0 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 6 0x2c 0x2b 0x2a 0x29 0x28 0x21*
Node 0x2c [Pin Complex] wcaps 0x400401: Stereo Pincap 0x00000020: IN Pin Default 0x593701f8: [N/A] CD at Int ATAPI Conn = Analog, Color = Unknown DefAssociation = 0xf, Sequence = 0x8 Misc = NO_PRESENCE Pin-ctls: 0x00: Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
What should this be? It doesn't seem to me there's any CD Audio connector in my motherboard. Is it supported by the codec anyway?
This mean that No physical connection for CD connector at the motherboard
Pin Default 0x593701f8
Bit 31:30 Port connectiviy
00b The Port Complex is connected to a jack (1/8", ATAPI, etc.). 01b No physical connection for Port. 10b A fixed function device (integrated speaker, integrated mic, etc.) is attached. 11b Both a jack and an internal device are attached. The Information provided in all other fields refers to the integrated device. The PD pin will reflect the status of the jack; the user will need to be queried to figure out what it is. _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Thank you for your clarification.
Regards
2011/5/27 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Must these controls be always coupled? Is it a specification constraint? What if via_hp_build() didn't execute
knew = via_clone_control(spec, &via_hp_mixer[1]);
when side_mute_status() returned '0' ?
If you disabled "Front Audio Panel" in BIOS, vt1718s_auto_create_hp_ctls() won't build any controls related to HP
Given actual implementation, those should be at least compatible to some extent; in case there were differences between nids in different 'flavours' of vt1718s ( for the sake of side_mute_channel(struct via_spec *spec) ), it should be possible to check spec->codec->vendor_id within the switch statement when spec->codec_type is VT1718S - the problem is finding the right nid
The last part is interesting. If vt2020 works the same way, the 8-channel setup should disallow the "Independent HP" function, that is it should be automatically turned off and 0x28 should be either muted, or used as a 'duplicate' for 0x0c (same sound of blue jack) or 0x08 (same sound as rear green jack, as in 'redirected audio' ). If I'm not misunderstanding everything, of course.
static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { .substreams = 2, .channels_min = 2, .channels_max = 10, .nid = 0x8, /* NID to query formats and rates */
This look like vt1718s support 10 channels and 10 channels allow independent HP and surround71 at the same time
BTW, 0x2a is connected to (gets input from) 0x09, which is labeled 'Surround Playback Volume' and is also an input for 0x25 ('Surround Playback Switch', black jack, rear speaker according to manual) throughout 0x19; 0x27 (missing gray jack) would be connected to 0x0b throughout 0x1a...
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
Tested: it works. I can get different streams out of rear (front playback) and front (hp) line out jacks (used mplayer on the 'default' rear channel(s) and aplay as above on the front panel)
so you can check whether 0xb can be used instead of 0xc for headphone
static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + AC_VERB_SET_CONNECT_SEL, pinsel ? + spec->hp_independent_mode_index : 0);
static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) { int err;
if (!pin) return 0; + if (spec->autocfg.line_outs == 4) { spec->multiout.hp_nid = 0xc; /* AOW4 */ + spec->hp_independent_mode_index = 2; + } + else { + spec->multiout.hp_nid = 0xb; spec->hp_independent_mode_index = 1; +}
static const struct hda_verb vt1718S_volume_init_verbs[] = {
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x2}, + {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, {0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
I haven't got an 8-channel system to test it; according to the manual, line in should be used to create an 8 channel setup. As I understand it, line-in (blue jack) should be a replacement for the gray jack when retasked.
struct via_spec {
... /* channel model */ const struct hda_channel_mode *channel_mode; int num_channel_mode; int const_channel_count; int ext_channel_count;
/* * channel mode setting */ static int via_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, spec->num_channel_mode); }
static int via_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, spec->ext_channel_count); }
static int via_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, &spec->ext_channel_count); if (err >= 0 && !spec->const_channel_count) { spec->multiout.max_channels = spec->ext_channel_count; } activate_ctl(spec->codec, "Side Playback Volume", spec->multiout.max_channels == 8); activate_ctl(spec->codec, "Side Playback Switch", spec->multiout.max_channels == 8); return err; }
static const struct hda_verb vt1718S_6ch_init[] = { { 0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, { } /* end */ };
static const struct hda_verb vt1718S_8ch_init[] = { { 0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, { 0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01 }, { } /* end */ };
static const struct hda_channel_mode vt1718S_modes[2] = { { 6, vt1718S_6ch_init }, { 8, vt1718S_8ch_init }, };
static const struct snd_kcontrol_new vt1718S_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Channel Mode", .info = via_ch_mode_info, .get = via_ch_mode_get, .put = via_ch_mode_put, }, { } };
/* add playback controls from the parsed DAC table */ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) {
... if (spec->autocfg.line_outs == 3) { /* and 0x2a can be retask as output pin */ nid_vol = 0xc; nid_mute = 0x2a; err = via_add_control( spec, VIA_CTL_WIDGET_VOL, "Side Playback Volume", HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT)); if (err < 0) return err; err = via_add_control( spec, VIA_CTL_WIDGET_MUTE, "Side Playback Switch", HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0, HDA_OUTPUT)); if (err < 0) return err;
spec->private_dac_nids[AUTO_SEQ_SIDE] = nid_vol; spec->const_channel_count = 6; spec->channel_mode = vt1718S_modes; spec->num_channel_mode = ARRAY_SIZE(vt1718S_modes); spec->mixers[spec->num_mixers] = vt1718S_chmode_mixer; spec->num_mixers++; } }
2011/5/31 Raymond Yau superquad.vortex2@gmail.com:
2011/5/27 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Must these controls be always coupled? Is it a specification constraint? What if via_hp_build() didn't execute
knew = via_clone_control(spec, &via_hp_mixer[1]);
when side_mute_status() returned '0' ?
If you disabled "Front Audio Panel" in BIOS, vt1718s_auto_create_hp_ctls() won't build any controls related to HP
Yes, that's something I had noticed in my tests: front panel disabled in bios -> no hp controls; front panel enabled in bios BUT not connected to the motherboard-> misc: no_presence for both 0x28 and 0x29.
But I was also asking for the following code:
static const struct snd_kcontrol_new via_hp_mixer[2] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Independent HP", .info = via_independent_hp_info, .get = via_independent_hp_get, .put = via_independent_hp_put, }, { .iface = NID_MAPPING, .name = "Independent HP", }, };
Must there be always two "Independent HP" controls in all via codecs, or there could be just one? In the latter case via_hp_mixer[1] could be ignored in some cases.
The last part is interesting. If vt2020 works the same way, the 8-channel setup should disallow the "Independent HP" function, that is it should be automatically turned off and 0x28 should be either muted, or used as a 'duplicate' for 0x0c (same sound of blue jack) or 0x08 (same sound as rear green jack, as in 'redirected audio' ). If I'm not misunderstanding everything, of course.
static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { .substreams = 2, .channels_min = 2, .channels_max = 10, .nid = 0x8, /* NID to query formats and rates */
This look like vt1718s support 10 channels and 10 channels allow independent HP and surround71 at the same time
If this part of the driver is correct, you're definitely right. That also means admin's answer at
http://www.viaarena.com/forums/showthread.php?t=41015
is mistaken when he says
"Please note that the “Independent Headphone” function requires two channels. Therefore, only six channels will be available if “Independent Headphone” is being used."
On the other hand, the picture of via's configuration panel seems to give him right: in "Independent HP" mode ("Auricular independiente" in the picture) the two side speakers for surround effects are grayed out as to mean they're disabled, whereas in 'Redirected Ouptut" ("Auricular redirigido" in the picture) those ones seem to be enabled. Though, there could be a lack of support for all ten channels in the motherboard implementation and/or a limitation in that particular version of via's driver/mixer (if possible at all, I'm just guessing...)
BTW, 0x2a is connected to (gets input from) 0x09, which is labeled 'Surround Playback Volume' and is also an input for 0x25 ('Surround Playback Switch', black jack, rear speaker according to manual) throughout 0x19; 0x27 (missing gray jack) would be connected to 0x0b throughout 0x1a...
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
Tested: it works. I can get different streams out of rear (front playback) and front (hp) line out jacks (used mplayer on the 'default' rear channel(s) and aplay as above on the front panel)
so you can check whether 0xb can be used instead of 0xc for headphone
Before testing your code:
static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
- AC_VERB_SET_CONNECT_SEL, pinsel ?
- spec->hp_independent_mode_index : 0);
This is to select entry at index #1 (which should be 0x0b) in the connection list of node 0x34 (the Audio Selector driving node 0x28) when Independent HP is selected, right?
[...cut...]
static const struct hda_verb vt1718S_volume_init_verbs[] = {
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
What's the param field's meaning here? Is it the index of a connection list to be selected? In this case, entry #0 for 0x34 should be 0x08, is it to start with Independent HP turned off?
For the rest of your code (6/8 channels mode selection and retasking part), shall I apply that altogether with the 0x0b selection part, or should I rather test if 0x0b is usable for headphone in place of 0x0c first?
I haven't got an 8-channel system to test it; according to the manual, line in should be used to create an 8 channel setup. As I understand it, line-in (blue jack) should be a replacement for the gray jack when retasked.
struct via_spec {
... /* channel model */ const struct hda_channel_mode *channel_mode; int num_channel_mode; int const_channel_count; int ext_channel_count;
/* * channel mode setting */ static int via_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, spec->num_channel_mode); }
static int via_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, spec->ext_channel_count); }
static int via_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, &spec->ext_channel_count); if (err >= 0 && !spec->const_channel_count) { spec->multiout.max_channels = spec->ext_channel_count; } activate_ctl(spec->codec, "Side Playback Volume", spec->multiout.max_channels == 8); activate_ctl(spec->codec, "Side Playback Switch", spec->multiout.max_channels == 8); return err; }
static const struct hda_verb vt1718S_6ch_init[] = { { 0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, { } /* end */ };
static const struct hda_verb vt1718S_8ch_init[] = { { 0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, { 0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01 }, { } /* end */ };
static const struct hda_channel_mode vt1718S_modes[2] = { { 6, vt1718S_6ch_init }, { 8, vt1718S_8ch_init }, };
static const struct snd_kcontrol_new vt1718S_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Channel Mode", .info = via_ch_mode_info, .get = via_ch_mode_get, .put = via_ch_mode_put, }, { } };
/* add playback controls from the parsed DAC table */ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, const struct auto_pin_cfg *cfg) {
... if (spec->autocfg.line_outs == 3) { /* and 0x2a can be retask as output pin */ nid_vol = 0xc; nid_mute = 0x2a; err = via_add_control( spec, VIA_CTL_WIDGET_VOL, "Side Playback Volume", HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT)); if (err < 0) return err; err = via_add_control( spec, VIA_CTL_WIDGET_MUTE, "Side Playback Switch", HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0, HDA_OUTPUT)); if (err < 0) return err;
spec->private_dac_nids[AUTO_SEQ_SIDE] = nid_vol; spec->const_channel_count = 6; spec->channel_mode = vt1718S_modes; spec->num_channel_mode = ARRAY_SIZE(vt1718S_modes); spec->mixers[spec->num_mixers] = vt1718S_chmode_mixer; spec->num_mixers++; } } _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
2011/6/2 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Must these controls be always coupled? Is it a specification constraint? What if via_hp_build() didn't execute
knew = via_clone_control(spec, &via_hp_mixer[1]);
when side_mute_status() returned '0' ?
But I was also asking for the following code:
static const struct snd_kcontrol_new via_hp_mixer[2] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Independent HP", .info = via_independent_hp_info, .get = via_independent_hp_get, .put = via_independent_hp_put, }, { .iface = NID_MAPPING, .name = "Independent HP", }, };
Must there be always two "Independent HP" controls in all via codecs, or there could be just one? In the latter case via_hp_mixer[1] could be ignored in some cases.
Refer to commit 3d83e577a8206f0f3822a3840e12f76477142ba2
There are codec which does not support indepedent HP
http://thread.gmane.org/gmane.linux.alsa.devel/68414
NID_MAPPING seem used for debugging only
The error "hda-codec: no NID for mapping control Independent HP:0:0" can be fixed by checking the value returned by side_mute_channel()
knew = via_clone_control(spec, &via_hp_mixer[0]); if (knew == NULL) return -ENOMEM;
knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; + + if (side_mute_channel(spec) == 0) + return 0;
knew = via_clone_control(spec, &via_hp_mixer[1]); if (knew == NULL) return -ENOMEM; knew->subdevice = side_mute_channel(spec);
The last part is interesting. If vt2020 works the same way, the 8-channel setup should disallow the "Independent HP" function, that is it should be automatically turned off and 0x28 should be either muted, or used as a 'duplicate' for 0x0c (same sound of blue jack) or 0x08 (same sound as rear green jack, as in 'redirected audio' ). If I'm not misunderstanding everything, of course.
static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { .substreams = 2, .channels_min = 2, .channels_max = 10, .nid = 0x8, /* NID to query formats and rates */
This look like vt1718s support 10 channels and 10 channels allow independent HP and surround71 at the same time
If this part of the driver is correct, you're definitely right. That also means admin's answer at
http://www.viaarena.com/forums/showthread.php?t=41015
is mistaken when he says
"Please note that the “Independent Headphone” function requires two channels. Therefore, only six channels will be available if “Independent Headphone” is being used."
On the other hand, the picture of via's configuration panel seems to give him right: in "Independent HP" mode ("Auricular independiente" in the picture) the two side speakers for surround effects are grayed out as to mean they're disabled, whereas in 'Redirected Ouptut" ("Auricular redirigido" in the picture) those ones seem to be enabled. Though, there could be a lack of support for all ten channels in the motherboard implementation and/or a limitation in that particular version of via's driver/mixer (if possible at all, I'm just guessing...)
The codec vt1708s mentioned in the thread is a 8 channel codec
if you look at vt1718S_auto_fill_dac_nids() and vt1718S_auto_create_hp_ctls() , grey jack use 0x0b and headphone use 0x0c
yes, it is still possible that vt1718s without a grey jack is just a 8 channel codec , but those variants of vt1718s which has a grey jack are most likely a 10 channel codec
/* fill in the dac_nids table from the parsed pin configuration */ static int vt1718S_auto_fill_dac_nids(struct via_spec *spec, const struct auto_pin_cfg *cfg) { int i; hda_nid_t nid;
spec->multiout.num_dacs = cfg->line_outs;
spec->multiout.dac_nids = spec->private_dac_nids;
for (i = 0; i < 4; i++) { nid = cfg->line_out_pins[i]; if (nid) { /* config dac list */ switch (i) { case AUTO_SEQ_FRONT: spec->private_dac_nids[i] = 0x8; break; case AUTO_SEQ_CENLFE: spec->private_dac_nids[i] = 0xa; break; case AUTO_SEQ_SURROUND: spec->private_dac_nids[i] = 0x9; break; case AUTO_SEQ_SIDE: spec->private_dac_nids[i] = 0xb; break; } } }
return 0; }
BTW, 0x2a is connected to (gets input from) 0x09, which is labeled 'Surround Playback Volume' and is also an input for 0x25 ('Surround Playback Switch', black jack, rear speaker according to manual) throughout 0x19; 0x27 (missing gray jack) would be connected to 0x0b throughout 0x1a...
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
Tested: it works. I can get different streams out of rear (front playback) and front (hp) line out jacks (used mplayer on the 'default' rear channel(s) and aplay as above on the front panel)
so you can check whether 0xb can be used instead of 0xc for headphone
Before testing your code:
static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
- AC_VERB_SET_CONNECT_SEL, pinsel ?
- spec->hp_independent_mode_index : 0);
This is to select entry at index #1 (which should be 0x0b) in the connection list of node 0x34 (the Audio Selector driving node 0x28) when Independent HP is selected, right?
Refer to commit cdc1784d49258198df600fbc1d37c07d7eee5ed6
and ce0e5a9e81fbb153ee15ca60246c6722f07fc546
it look like spec->hp_independent_mode_index is used to select the path for HP pin to [Audio Output]
(e..g. vt1702 is using spec->hp_independent_mode_index = 0
Node 0x10 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Front Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Device: name="VT1702 Analog", type="Audio", device=0 Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
Node 0x17 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Control: name="Independent HP", index=0, device=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0000001c: OUT HP Detect Pin Default 0x0221401f: [Jack] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0xf Pin-ctls: 0xc0: OUT HP Unsolicited: tag=05, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 2 0x1d 0x1a*
Node 0x1a [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Control: name="Master Front Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Master Front Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x09 0x09] [0x00 0x00] [0x00 0x00] [0x00 0x00] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 4 0x10 0x14 0x15 0x18
Node 0x1d [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Headphone Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x2a, nsteps=0x2a, stepsize=0x05, mute=0 Amp-Out vals: [0x2a 0x2a] Converter: stream=0, channel=0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0
[...cut...]
static const struct hda_verb vt1718S_volume_init_verbs[] = {
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
What's the param field's meaning here? Is it the index of a connection list to be selected? In this case, entry #0 for 0x34 should be 0x08, is it to start with Independent HP turned off?
For the rest of your code (6/8 channels mode selection and retasking part), shall I apply that altogether with the 0x0b selection part, or should I rather test if 0x0b is usable for headphone in place of 0x0c first?
The 6/8 channel mode switch is based on vt2020 is a 10 channel codec so you have to check whether [Audio Output] 0x0b can be used
2011/6/7 Raymond Yau superquad.vortex2@gmail.com:
2011/6/2 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Must these controls be always coupled? Is it a specification constraint? What if via_hp_build() didn't execute
knew = via_clone_control(spec, &via_hp_mixer[1]);
when side_mute_status() returned '0' ?
But I was also asking for the following code:
static const struct snd_kcontrol_new via_hp_mixer[2] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Independent HP", .info = via_independent_hp_info, .get = via_independent_hp_get, .put = via_independent_hp_put, }, { .iface = NID_MAPPING, .name = "Independent HP", }, };
Must there be always two "Independent HP" controls in all via codecs, or there could be just one? In the latter case via_hp_mixer[1] could be ignored in some cases.
Refer to commit 3d83e577a8206f0f3822a3840e12f76477142ba2
There are codec which does not support indepedent HP
http://thread.gmane.org/gmane.linux.alsa.devel/68414
NID_MAPPING seem used for debugging only
The error "hda-codec: no NID for mapping control Independent HP:0:0" can be fixed by checking the value returned by side_mute_channel()
knew = via_clone_control(spec, &via_hp_mixer[0]); if (knew == NULL) return -ENOMEM;
knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid;
- if (side_mute_channel(spec) == 0)
- return 0;
knew = via_clone_control(spec, &via_hp_mixer[1]); if (knew == NULL) return -ENOMEM; knew->subdevice = side_mute_channel(spec);
That's something I was thinking about, but wasn't sure if it was possible (and safe) to ignore via_hp_mixer[1]. Now I'll apply this. (Perhaps, by adding a further hda_nid_t variable one could avoid calling side_mute_channel twice: at the beginning:
- hda_nid_t nid; + hda_nid_t nid, side_nid;
then:
+ if( ( side_nid = side_mute_channel(spec) ) == 0 ) + return 0;
knew = via_clone_control(spec, &via_hp_mixer[1]); if (knew == NULL) return -ENOMEM; - knew->subdevice = side_mute_channel(spec); + knew->subdevice = side_nid;
though not that much important).
The last part is interesting. If vt2020 works the same way, the 8-channel setup should disallow the "Independent HP" function, that is it should be automatically turned off and 0x28 should be either muted, or used as a 'duplicate' for 0x0c (same sound of blue jack) or 0x08 (same sound as rear green jack, as in 'redirected audio' ). If I'm not misunderstanding everything, of course.
static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { .substreams = 2, .channels_min = 2, .channels_max = 10, .nid = 0x8, /* NID to query formats and rates */
This look like vt1718s support 10 channels and 10 channels allow independent HP and surround71 at the same time
If this part of the driver is correct, you're definitely right. That also means admin's answer at
http://www.viaarena.com/forums/showthread.php?t=41015
is mistaken when he says
"Please note that the “Independent Headphone” function requires two channels. Therefore, only six channels will be available if “Independent Headphone” is being used."
On the other hand, the picture of via's configuration panel seems to give him right: in "Independent HP" mode ("Auricular independiente" in the picture) the two side speakers for surround effects are grayed out as to mean they're disabled, whereas in 'Redirected Ouptut" ("Auricular redirigido" in the picture) those ones seem to be enabled. Though, there could be a lack of support for all ten channels in the motherboard implementation and/or a limitation in that particular version of via's driver/mixer (if possible at all, I'm just guessing...)
The codec vt1708s mentioned in the thread is a 8 channel codec
Sorry for my insistence, I had confused codec names... However, 0x0b doesn't seem to send audio to front panel line-out (I had made a few tests an was going to post results, more details below).
if you look at vt1718S_auto_fill_dac_nids() and vt1718S_auto_create_hp_ctls() , grey jack use 0x0b and headphone use 0x0c
I see, and indeed, in /proc/asound/card0/codec#0, node 0x27 (missing gray jack) is (would be) connected to 0x0b via 0x1a. Though 0x2a seems to be connectable only to 0x09 ("Surround Playback Volume" - currently labeled with an asterisk in 0x2a's connection list) and 0x0c, so adding support for retasking blue jack as side in codec vt2020/vt1718s without a grey jack could require some more effort to handle Independent HP correctly (given 0x0b looks like unusable to 'drive' 0x28)... unless there could be some sort of 'confusion' between 0x2a's and 0x29's connection lists, given the latter is connected to 0x0b via 0x1c and 0x35 (that is, could respective connection lists be 'inverted' somehow? does it make sense? or is bios-derived autoconfig the only one usable?).
yes, it is still possible that vt1718s without a grey jack is just a 8 channel codec , but those variants of vt1718s which has a grey jack are most likely a 10 channel codec
That's a chance, unless 0x2a could be connected to 0x0b so that 0x0c remained available for HP (I guess). Otherwise, 0x0c should be used as side and front panel hp should be either muted or get input from 0x08 (front, as in redirected output) or 0x0c ('new' side) - again, I'm guessing.
In alsa,
when independent HP is on,
The HP jack is supposed to connected to [Audio Output] which is not used by the rear panel jacks (i.e. 0x25) and application has to use sudevice 1
you can use aplay -Dhw:0,0,1 stereo.wav
Tested: it works. I can get different streams out of rear (front playback) and front (hp) line out jacks (used mplayer on the 'default' rear channel(s) and aplay as above on the front panel)
so you can check whether 0xb can be used instead of 0xc for headphone
Before testing your code:
static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
- AC_VERB_SET_CONNECT_SEL, pinsel ?
- spec->hp_independent_mode_index : 0);
[...cut...]
static const struct hda_verb vt1718S_volume_init_verbs[] = {
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
- {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
I've tried this part, along with:
static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) { int err;
if (!pin) return 0; + if (spec->autocfg.line_outs == 4) { spec->multiout.hp_nid = 0xc; /* AOW4 */ + spec->hp_independent_mode_index = 2; + } + else { + spec->multiout.hp_nid = 0xb; spec->hp_independent_mode_index = 1; +}
(from your previous message, reposting for clarity and reference)
but got no audio with aplay -Dhw:0,0,1 stereo.wav
On my first attempt, I noticed node 0x0c still got control "Headphone Playback Volume", thus I modified vt1718S_auto_create_hp_ctls() so that:
err = via_add_control(spec, VIA_CTL_WIDGET_VOL, "Headphone Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); + HDA_COMPOSE_AMP_VAL(spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
which labeled 0x0b as "Headphone Playback Volume", but still no output came from there; I've also tried to change
{0x34, AC_VERB_SET_CONNECT_SEL, 0x0}
into
{0x34, AC_VERB_SET_CONNECT_SEL, 0x1}
and
{0x35, AC_VERB_SET_CONNECT_SEL, 0x1}
into
{0x35, AC_VERB_SET_CONNECT_SEL, 0x0} or {0x35, AC_VERB_SET_CONNECT_SEL, 0x2}
in case some weird conflict happened when both 0x34 and 0x35 where initialized with/switched to the same connection, still to no avail.
I've also applied a piece of code you posted earlier and retried those combinations, but nothing changed -- code being:
static const struct hda_verb vt1718S_volume_init_verbs[] = {
/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
(apparently should be unrelated, though trying to access a connection that doesn't exist for 0x21 shouldn't be very safe/correct, so I've kept the above).
This other code (from your same message addressing 0x21 access to a wrong connection):
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = + ( snd_hda_find_mixer_ctl(codec, "Independent HP") ? 2 : 1);
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
didn't work at all:
executing 'aplay -Dhw:0,0,1 stereo.wav' failed with error:
aplay: main:660: audio open error: Device or resource busy
executing 'aplay -l' showed the second subdevice for card#0 analog device hadn't been created:
**** List of PLAYBACK Hardware Devices **** card 0: SB [HDA ATI SB], device 0: VT2020 Analog [VT2020 Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 0: SB [HDA ATI SB], device 1: VT2020 Digital [VT2020 Digital] Subdevices: 2/2 Subdevice #0: subdevice #0 Subdevice #1: subdevice #1 card 1: HDMI [HDA ATI HDMI], device 3: HDMI 0 [HDMI 0] Subdevices: 1/1 Subdevice #0: subdevice #0
(this happened with front audio panel _enabled_ in BIOS)
Adding a few printk()'s to file "patch_via.c" showed me function via_hp_build() is called before via_build_pcms() (unless front panel is disabled in BIOS, in which case via_hp_build() isn't invoked at all), therefore, when a control "Independent HP" is created, it should be 'visible' by via_build_pcms(); however, snd_hda_find_mixer_ctl(codec, "Independent HP") fails to find it until the following loop is executed inside via_build_controls:
for (i = 0; i < spec->num_mixers; i++) { err = snd_hda_add_new_ctls(codec, spec->mixers[i]); if (err < 0) return err; }
and via_build_controls() is called after via_build_pcms(), but then it's too late (or seemed to be such) to modify the number of playback substreams. At last, I've tried the following, which worked:
static int via_build_pcms(struct hda_codec *codec) { struct via_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; + const struct snd_kcontrol_new *knew; + int index, found=0;
[ ... ] info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; + + /* is this a multistream-capable environment? let's assume no and check if yes instead */ + info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 1; + for( index = 0; index < spec->num_mixers; index++ ){ + knew = spec->mixers[ index ]; + while( knew->name ){ + if( !strcmp( knew->name, "Independent HP" ) ){ + /* it looks like there's a front panel */ + info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 2; + found = 1; + break; + } + knew++; + } + if( found ) + break; + } + info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
(I'm omitting debug printk() calls and the rest of the function)
But, perhaps, struct via_spec could have a flag initialized to zero (somewhere, before via_hp_build() and via_build_pcms() are invoked, perhaps in via_new_spec() ) and set to 1 when via_hp_build() succeeds cloning via_hp_mixer[0], that is:
knew = via_clone_control(spec, &via_hp_mixer[0]); if (knew == NULL) return -ENOMEM;
knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; + spec->front_panel = HDA_HW_WITH_FRONT_PANEL;
( "#define HDA_HW_WITH_FRONT_PANEL 1" and "#define HDA_HW_WITHOUT_FRONT_PANEL 0" put somewhere in the file)
so that via_build_pcms() could just do something like:
info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 1 + spec->front_panel;
but via_hp_build() is called if spec->hp_mux is not null, therefore one might think (mistakenly, according to me) to do just the following:
info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = ( spec->hp_mux ? 2 : 1 );
however, that shouldn't work, because even if spec->hp_mux has been created, via_hp_build() might not create an "Independent HP" control, for instance because of a wrong number of connections to the relevant nid:
if (spec->codec_type != VT1708) { nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); if (nums <= 1) return 0; }
Anyway, I'm posting output of asla-info.sh for the above code I've tested with front audio panel disabled in BIOS (the loop inside via_build_pcms, I mean, for now I've preferred not to touch struct via_spec)
By the way, should something like the above be done for capture streams as well? I've noticed (with front panel disabled) that controls "Front Mic Playback Volume" and "Front Mic Playback Switch" are correctly missing from audio-mixer widget 0x21, but node 0x29 is still 'attached' to control "Front Mic Boost Capture Volume", which is accessible through a mixer (though I didn't try to play with it; it is listed also by amixer output in above linked document). Is this the wanted/expected behaviour? (I understand there must be, anyway, two captures and two input sources, because there's still one line-in plus one (rear) mic, plus stereo-mix to deal with, and one "boost capture volume" control for the rear mic does make sense, my doubt is about its corresponding control for the now missing front mic).
If there are any other tests you wish me to do (such as sending raw verbs to the hw and posting results), just let me know.
2011/6/8 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
2011/6/7 Raymond Yau superquad.vortex2@gmail.com:
2011/6/2 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
if you look at vt1718S_auto_fill_dac_nids() and vt1718S_auto_create_hp_ctls() , grey jack use 0x0b and headphone use 0x0c
I see, and indeed, in /proc/asound/card0/codec#0, node 0x27 (missing gray jack) is (would be) connected to 0x0b via 0x1a. Though 0x2a seems to be connectable only to 0x09 ("Surround Playback Volume" - currently labeled with an asterisk in 0x2a's connection list) and 0x0c, so adding support for retasking blue jack as side in codec vt2020/vt1718s without a grey jack could require some more effort to handle Independent HP correctly (given 0x0b looks like unusable to 'drive' 0x28)... unless there could be some sort of 'confusion' between 0x2a's and 0x29's connection lists, given the latter is connected to 0x0b via 0x1c and 0x35 (that is, could respective connection lists be 'inverted' somehow? does it make sense? or is bios-derived autoconfig the only one usable?).
yes, it is still possible that vt1718s without a grey jack is just a 8 channel codec , but those variants of vt1718s which has a grey jack are most likely a 10 channel codec
That's a chance, unless 0x2a could be connected to 0x0b so that 0x0c remained available for HP (I guess). Otherwise, 0x0c should be used as side and front panel hp should be either muted or get input from 0x08 (front, as in redirected output) or 0x0c ('new' side) - again, I'm guessing.
Another weird (or even weirder) idea: could there be some sort of 'internal switch' (hidden/non-accessible) allowing 0x0b to be used for HP only when 0x0c is connected to 0x2a and 0x2a is retasked as output? I'd wish to check it by the mean of the code you had proposed for line-in/side retasking, with some changes to it (and the rest), but I'd need some help to complete the code; if it didn't work, I think that could be a base to turn off Independent HP in 7.1 mode.
The logic should be as follows:
- In function vt1718S_auto_create_hp_ctls(), let's attach a 'fake' control "Headphone Playback Volume #2" to widget 0x0b:
...... + if (spec->autocfg.line_outs == 3){ + err = via_add_control(spec, VIA_CTL_WIDGET_VOL, + "Headphone Playback Volume #2", + HDA_COMPOSE_AMP_VAL(0xb, 3, 0, HDA_OUTPUT)); + if (err < 0) + return err; + }
- In function via_independent_hp_put() let's use pinsel, spec->hp_independent_mode_index and spec->ext_channel_count (or spec->multiout.max_channels ?) to choose whether to select 0x0c (connection #2) and activate control "Headphone Playback Volume" or to select 0x0b (conn #1) and activate control "Headphone Playback Volume #2":
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; + unsigned int ch6_mode = 1; + char * vol_ctl_name = "Headphone Playback Volume"; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; - if (spec->codec_type == VT1718S) + if (spec->codec_type == VT1718S){ + if( spec->ext_channel_count == 8 ){ + /* or should it be if(spec->multiout.max_channels == 8) ? */ + ch6_mode = 0; + vol_ctl_name = "Headphone Playback Volume #2" + } snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + AC_VERB_SET_CONNECT_SEL, pinsel ? + ( spec->hp_independent_mode_index + ch6_mode ) : 0); + } else ......... - activate_ctl(codec, "Headphone Playback Volume", + activate_ctl(codec, vol_ctl_name, spec->hp_independent_mode); activate_ctl(codec, "Headphone Playback Switch", spec->hp_independent_mode);
- In new function via_ch_mode_put(), after calling snd_hda_ch_mode_put(), let's do the following:
1. If going to retask 0x2a as side ( spec->ext_channel_count == 8 or spec->multiout.max_channels == 8 ?)
1.1 If "Independent HP" is on (spec->hp_independent_mode == 1) 1.1.2 mute headphones (with activate_ctl() on corresponding volume and switch controls, or with snd_hda_codec_write()? or both?)
1.2 Set spec->multiout.hp_nid to 0x0b
1.3 Activate Side Playback Volume and Switch controls
1.4 If "Independent HP" was on 1.4.1 re-enable it ( select connection 1 (0x0b) for nid 0x34, call snd_hda_codec_setup_stream() if needed, call activate_ctl properly)
2. Else (if going from 8 to 6 channels) 2.1 behave as above, but using 0x0c for HP and disabling Sid controls
(1 and 2 can be 'collapsed' by the mean of a few variables to be set after first check)
The above assumes that (somewhere) the driver 'synchronizes' accesses to mixer widgets so that no more than one ".put method" can be called at a time (to handle side effects on other widgets correctly), otherwise, if via_independent_hp_put() and via_ch_mode_put() were called at the same time, some race condition/undefined behaviour could show up.
Anyway, does it make sense? (eventually changed so that Independent HP is always turned off when 0x2a is retasked as Side).
BTW, there's something I don't understand in your code for via_ch_mode_put()
static int via_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, &spec->ext_channel_count);
/****** WHY THE FOLLOWING? ******/ if (err >= 0 && !spec->const_channel_count) { spec->multiout.max_channels = spec->ext_channel_count; }/****** uppercase in comment just to catch attention ******/
activate_ctl(spec->codec, "Side Playback Volume", spec->multiout.max_channels == 8); activate_ctl(spec->codec, "Side Playback Switch", spec->multiout.max_channels == 8); return err; }
AFAICT, spec->const_channel_count is initialized to 6 in vt1718S_auto_create_multi_out_ctls() if spec->autocfg.line_outs == 3, in which case
spec->mixers[spec->num_mixers] = vt1718S_chmode_mixer;
is executed and vt1718S_chmode_mixer will be 'registered' by via_build_controls(); otherwise, spec->const_channel_count is 0 (as via_new_spec() allocates a block of memory initialized to zero by kzalloc()) but the mixer isn't registered and thus via_ch_mode_put() should never be called; I can't find another place where spec->const_channel_mode is modified. Perhaps, should that be:
if (err >= 0) { spec->multiout.max_channels = spec->ext_channel_count; } else { return err; /* to avoid messing with the rest, specially if touching HP */ }
or am I missing something?
IMPORTANT UPDATE!!!!!
Node 0x0b can drive HP! The problem was function set_widgets_power_state_vt1718S() not updating power state for the correct nid, solved as follows:
static void set_widgets_power_state_vt1718S(struct hda_codec *codec) { ... if (spec->hp_independent_mode) { - /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ + /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) of AOW3 (bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xc, 0, + snd_hda_codec_write(codec, spec->multiout.hp_nid, 0, AC_VERB_SET_POWER_STATE, parm); }
Anyway, there's another problem with hp_independent_mode_index when there are four line-outs:
as suggested in a previous mail (with additional comment where problems arise), in vt1718S_auto_create_hp_ctls()
if (spec->autocfg.line_outs == 4) { spec->multiout.hp_nid = 0xc; /* AOW4 */ spec->hp_independent_mode_index = 2; /* <- TROUBLES! */ }else{ spec->multiout.hp_nid = 0xb; spec->hp_independent_mode_index = 1; }
but in via_independent_hp_put():
unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; /* <- TROUBLES! */
When turning on Independent HP mode for codec VT1718S, pinsel is 1, when turning it off that's 0, thus, if spec->hp_independent_mode_index is 2, spec->hp_independent_mode is always 0 (condition spec->hp_independent_mode_index == pinsel alwyas fails) and corresponding controls can't be activated:
/* update HP volume/swtich active state */ if (spec->codec_type == VT1708S || spec->codec_type == VT1702 || spec->codec_type == VT1718S || spec->codec_type == VT1716S || VT2002P_COMPATIBLE(spec)) { activate_ctl(codec, "Headphone Playback Volume", spec->hp_independent_mode); activate_ctl(codec, "Headphone Playback Switch", spec->hp_independent_mode); }
I can confirm this in my system (3 line_outs) - I've used a printk() to log the value of pinsel - but I guess that's the same with 4 line_outs (that is, codec vt1718s with gray jack), because old code always set hp_independent_mode_index to 1. I can see two solutions for this:
1) Use different values for spec->hp_independent_mode_index, in vt1718S_auto_create_hp_ctls(), basing on available jacks (as in above code), and change via_independent_hp_put() as follows:
/* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; - if (spec->codec_type == VT1718S) + if (spec->codec_type == VT1718S){ + /* when turning on Independent HP for VT1718S pinsel is 1 but */ + /* spec->hp_independent_mod_index can be 1 or 2 */ + if( ( spec->hp_independent_mode_index == 2 ) && ( pinsel == 1 ) ) + spec->hp_independent_mode = 1; snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + AC_VERB_SET_CONNECT_SEL, pinsel ? + spec->hp_independent_mode_index : 0); + } else snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel);
(call to snd_hda_codec_write as modified in your previous suggestion)
This choice would be consistent with the idea that spec->hp_independent_mode_index is the index of the audio selector widget's connection list to select when turning Independent HP mode on. If struct via_spec had another field to tell the index of the front connection, let's call it hp_redirected_mode_index, the else statement above could be avoided and the code could become:
/* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) /* when turning on Independent HP for VT1718S pinsel is 1 but */ /* spec->hp_independent_mod_index can be 1 or 2 */ if( ( spec->hp_independent_mode_index == 2 ) && ( pinsel == 1 ) ) spec->hp_independent_mode = 1;
snd_hda_codec_write( codec, nid, 0, AC_VERB_SET_CONNECT_SEL, ( spec->hp_independent_mode ? spec->hp_independent_mode_index : spec->hp_redirected_mode_index ) );
(I'm not using a diff-alike format here to improve readability)
Of course, that would require each vtxxxx_auto_create_hp_ctls() to be modified so that (new field) spec->hp_redirected_mode_index were initialized the right way (e.g. with the index of the "Front Playback Volume" control nid). Notice that, as a side effect, there would be no more dependence on pinsel value in call to snd_hda_codec_write, that could be a safe behavior in case pinsel value were wrong (if possible at all, e.g. because of a bug in a mixer application), in which case the worst possible effect would be to turn off Independent HP unwillingly, but no bad value would be passed to snd_hda_codec_write (again, this is meaningful only if pinsel, that is ucontrol->value.enumerated.item[0], may come from a user space mistaken call to driver's interface). If this is wise, I'd suggest to consider it.
2) Leave spec->hp_independent_mode_index = 1 in vt1718S_auto_create_hp_ctls():
starting from your suggested code:
if (spec->autocfg.line_outs == 4) { spec->multiout.hp_nid = 0xc; /* AOW4 */ - spec->hp_independent_mode_index = 2; }else{ spec->multiout.hp_nid = 0xb; - spec->hp_independent_mode_index = 1; } + spec->hp_independent_mode_index = 1; /* this was yet here in older code */
(without the comment of course)
and changing via_independent_hp_put() the following way:
/* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; if (spec->codec_type == VT1718S) snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + AC_VERB_SET_CONNECT_SEL, pinsel ? + ( spec->hp_independent_mode_index + + ( spec->multiout.hp_nid == 0xc ) ) : 0); else snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel);
In this case, spec->hp_independent_mode is evaluated only once, uniformly and consistently for all codecs, though it seems to me hp_independent_mode_index use is a bit less consistent with its intended meaning. Anyway, I think both solutions are viable. (personally, I'd prefer the variant to the former one - less dependent on pinsel value, but that must make sense to be chosen).
------------------------------------
With respect to your proposed code for retasking blue jack as side, as far as I understand it, I think it should work, but could require other changes to set_widgets_power_state_vt1718S(), for instance:
/* PW1 (25h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x2a, &parm); snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm); + + /* PW6 (2ah), AOW4 (ch) */ + /* avoiding to conflict with Independent HP when its AOW is 4 (ch)*/ + if( spec->autocfg.line_outs == 3 ){ + parm = AC_PWRST_D3; + /* if a 7.1 system is connected, let's change the */ + /* state of 0x0c into D0 else change it into D3 */ + if( spec->ext_channel_count == 8 ){ + set_pin_power_state( codec, 0x2a, &parm ); + snd_hda_codec_write( codec, 0xc, 0, AC_VERB_SET_POWER_STATE, parm); + }
if (spec->hp_independent_mode) { ....
(or perhaps should it be "if( spec->multiout.max_channels == 8 )" to be checked?)
Maybe also:
/* outputs */ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm); + /* avoiding to interfere with Independent HP when PW3 misses*/ + if( spec->autocfg.line_outs == 4 ) + snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
So that, when Independent HP mode is on and there are only 3 line-outs (missing grey jack, HP connected to 0x0b), and the function is not called because of a change in Independent HP state, sound is not turned off and on in sequence (given 0x0b would pass from state D0 to D3 because of 0x27 missing, then again to D0 because of Independent HP mode being active) - though such a change could be enough fast not to be noticeable (whether noticeable or not might vary based on scenarios).
Perahps, also:
/* inputs */ /* PW 5/6/7 (29h/2ah/2bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x29, &parm); - set_pin_power_state(codec, 0x2a, &parm); + /* ensuring PW6 (2ah) is still an input widget before treating it as such */ + if( ( spec->autocfg.line_outs == 4 || spec->ext_channel_count != 8) + && !spec->smart51_enabled ) + set_pin_power_state(codec, 0x2a, &parm); - set_pin_power_state(codec, 0x2b, &parm); + /* ensuring PW7 (2bh) is still an input widget before treating it as such */ + if( !spec->smart51_enabled ) + set_pin_power_state(codec, 0x2b, &parm); if (imux_is_smixer) parm = AC_PWRST_D0; /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
(or perhaps should it be " spec->multiout.max_channels != 8 " to be checked up?)
This is just to avoid repeating actions (e.g. calling set_pin_power_state twice on 0x2a as input and as retasked output) and treating jacks retasked as output as if they were still inputs, so that some widgets can be turned on/off more appropriately (e.g. 0x2a is the only one setting parm to D0 value but is retasked as output, and imux_is_smixer is false). (this part could be improved further, I guess, taking care of what is actually connected to 0x1e and 0x1f)
But perhaps smart51 checks should be removed from this codec's power state settings (since it's got more than 2 line-outs anyway).
Moreover:
/* PW0 (24h), AOW0 (8h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x24, &parm); - if (!spec->hp_independent_mode) /* check for redirected HP */ + if ( !spec->hp_independent_mode ){ /* check for redirected HP */ + /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) of AOW3 (bh) */ + /* turning on/off widgets connected to PW4 appropriately*/ + unsigned int parm2 = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm2); + snd_hda_codec_write( codec, 0x1b, 0, + AC_VERB_SET_POWER_STATE, parm2); + snd_hda_codec_write( codec, 0x34, 0, + AC_VERB_SET_POWER_STATE, parm2); + /* turning off hp_nid since unused in redirected output */ + snd_hda_codec_write( codec, spec->multiout.hp_nid, 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + /* if PW4 (28h) is in D0 then AOW0 (8h) must be set to D0 */ + if( parm2 == AC_PWRST_D0 ) + parm = parm2; + } snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
However, I have _not_ tested changes to power state settings (but for enabling 0xb to send output to HP - first part of this mail), so I'm asking if the above make sense at all. If it does, specially for what concern blue jack retasking, perhaps also:
static int via_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { ... + /* update jack power state */ + set_widgets_power_state(codec); return err; }
Same as done, before returning, in both via_independent_hp_put() and via_smart51_put() - unless its done implicitly (e.g. when calling snd_hda_ch_mode_put() - it doesn't seems to me that function can change power states, but I may be misunderstanding its operations).
--------------------------------------------------
Lastly, I don't understand the following:
static const struct hda_verb vt1718S_volume_init_verbs[] = { ... /* Setup default input of Front HP to MW9 */ {0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
In my system, 0x28 has just one connection, thus there's no connection at index 1 (and no more than 6 "Audio Mixer" widgets. Or... what am I misunderstanding there?
Node 0x28 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x0221401f: [Jack] HP Out at Ext Front Conn = 1/8, Color = Green DefAssociation = 0x1, Sequence = 0xf Pin-ctls: 0xc0: OUT HP VREF_HIZ Unsolicited: tag=21, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 1 0x1b
2011/6/12 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
IMPORTANT UPDATE!!!!!
Node 0x0b can drive HP! The problem was function set_widgets_power_state_vt1718S() not updating power state for the correct nid, solved as follows:
static void set_widgets_power_state_vt1718S(struct hda_codec *codec) { ... if (spec->hp_independent_mode) {
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) of AOW3 (bh) */
parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- snd_hda_codec_write(codec, spec->multiout.hp_nid, 0,
AC_VERB_SET_POWER_STATE, parm); }
Can your hear the same signal from black and orange jack when you playing stereo to hw:0,0,0 ?
if you look at snd_hda_multi_out_analog_prepare() in hda_codec.c,
if mout->no_share_stream=0 ,it seem that there is "upmix" feature when mout->num_dacs is 4 for those 5 jacks/6 jacks motherboard
i.e. the black and orange jacks can have the same signal as the green jack
/* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); if (!mout->no_share_stream && mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
/* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } return 0; }
but in via_independent_hp_put():
unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; /* <- TROUBLES! */
When turning on Independent HP mode for codec VT1718S, pinsel is 1, when turning it off that's 0, thus, if spec->hp_independent_mode_index is 2, spec->hp_independent_mode is always 0 (condition spec->hp_independent_mode_index == pinsel alwyas fails) and corresponding controls can't be activated:
/* update HP volume/swtich active state */ if (spec->codec_type == VT1708S || spec->codec_type == VT1702 || spec->codec_type == VT1718S || spec->codec_type == VT1716S || VT2002P_COMPATIBLE(spec)) { activate_ctl(codec, "Headphone Playback Volume", spec->hp_independent_mode); activate_ctl(codec, "Headphone Playback Switch", spec->hp_independent_mode); }
if the hp jack can also use "copy front" mode for "redirected headphone"
the driver don't need to disable "Headphone Playback Volume" for those 10 channels codecs or change the connection in via_independent_hp_put()
For those 3 jacks motherobard, "channel mode" 6-8 or "Use HP as Side" switch may just need tot switch the connection to use 0x0b or 0x0c if 0b has "Side Playback Volume" and 0x0c has "Headphone Playback Volume"
2011/6/19 Raymond Yau superquad.vortex2@gmail.com:
2011/6/12 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
IMPORTANT UPDATE!!!!!
Node 0x0b can drive HP! The problem was function set_widgets_power_state_vt1718S() not updating power state for the correct nid, solved as follows:
static void set_widgets_power_state_vt1718S(struct hda_codec *codec) { ... if (spec->hp_independent_mode) {
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) of AOW3 (bh) */
parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- snd_hda_codec_write(codec, spec->multiout.hp_nid, 0,
AC_VERB_SET_POWER_STATE, parm); }
Can your hear the same signal from black and orange jack when you playing stereo to hw:0,0,0 ?
if you look at snd_hda_multi_out_analog_prepare() in hda_codec.c,
if mout->no_share_stream=0 ,it seem that there is "upmix" feature when mout->num_dacs is 4 for those 5 jacks/6 jacks motherboard
i.e. the black and orange jacks can have the same signal as the green jack
/* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); if (!mout->no_share_stream && mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
/* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } return 0; }
I fear I cannot test it the best way (I've got a 5.1 system, but have some 'logistic' problems using it). I've made an attempt by using two headphones, connected as follows:
1) one to (rear) green jack, one to orange, 2) one to green, one to black, 3) one to orange, one to black,
and played a short two-channels file with aplay -Dhw:0,0,0 stereo.wav a few times, in each case I was able to here (same) sound from both headsets.
However, it would seem to me that snd_hda_multi_out_analog_prepare() is not used by VIA Codecs, instead, some pcm operations are defined within patch_via.c and used by each codec, e.g.
static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { .substreams = 2, .channels_min = 2, .channels_max = 10, .nid = 0x8, /* NID to query formats and rates */ .ops = { .open = via_playback_pcm_open, .prepare = via_playback_multi_pcm_prepare, .cleanup = via_playback_multi_pcm_cleanup, .close = via_pcm_open_close, }, };
(not all codec use via_pcm_open_close, actually)
None of them calls snd_hda_multi_out_analog_{prepare, cleanup}() for analog stuff, instead, part of the code in those (general) functions is reused and modified, and spec->multiout.no_share_stream isn't used, nor initialized (AFAICT).
By the way, my modification to set_widgets_power_state_vt1718S you've quoted is due to 0x0b being set to D3 because side is missing:
/* outputs */ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
Since 0x27 is not present, parm is not changed in set_pin_power_state() and 0x0b is 'turned off'. Therefore, if 0x0b must/can be used for independent hp, power state cannot be changed for a fixed nid, but current value for spec->multiout.hp_nid have to be used.
By the way, since via_playback_pcm_open() calls snd_hda_multi_out_analog_open(), which is the last one touching runtime->hw.channels_max, the problem you pointed out in your previous mail to report the right number of max channels for a substream, perhaps, could be solved the following way:
in file hda_codec.c:
/** -* snd_hda_multi_out_analog_open - open analog outputs +* snd_hda_multiout_analog_open_set - open analog outputs * * Open analog outputs and set up the hw-constraints. * If the digital outputs can be opened as slave, open the digital * outputs, too. */ -int snd_hda_multi_out_analog_open(struct hda_codec *codec, +int snd_hda_multiout_analog_open_set(struct hda_codec *codec, struct hda_multi_out *mout, struct snd_pcm_substream *substream, - struct hda_pcm_stream *hinfo) + struct hda_pcm_stream *hinfo, int max_channels) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.channels_max = mout->max_channels; + if( max_channels > 0 && max_channels <= mout->max_channels) + runtime->hw.channels_max = max_channels; + else + runtime->hw.channels_max = mout->max_channels; if (mout->dig_out_nid) { ....
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open); +EXPORT_SYMBOL_HDA(snd_hda_multiout_analog_open_set);
+/** + * snd_hda_multi_out_analog_open - open analog outputs + * + * Open analog outputs and set up the hw-constraints. + * If the digital outputs can be opened as slave, open the digital + * outputs, too. + */ +int snd_hda_multi_out_analog_open(struct hda_codec *codec, + struct hda_multi_out *mout, + struct snd_pcm_substream *substream, + struct hda_pcm_stream *hinfo) +{ + snd_hda_multiout_analog_open_set( codec, mout, substream, hinfo, 0 ); +} +EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
(to avoid breaking compatibility)
in file patch_via.c:
static int via_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { struct via_spec *spec = codec->spec; int idle = substream->pstr->substream_opened == 1 && substream->ref_count == 0; analog_low_current_mode(codec, idle); - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); + return snd_hda_multiout_analog_open_set( codec, &spec->multiout, substream, + hinfo, ( substream->number == 1 ? 2 + : spec->multiout.max_channels ) ); }
(substream->number is the same as subdevice, because their matching is tested in snd_pcm_attach_substream())
However, since the question is more general, and could affect other hda (and non-hda) codecs/drivers, a careful discussion on the general design could be needed.
but in via_independent_hp_put():
unsigned int pinsel = ucontrol->value.enumerated.item[0]; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; /* <- TROUBLES! */
When turning on Independent HP mode for codec VT1718S, pinsel is 1, when turning it off that's 0, thus, if spec->hp_independent_mode_index is 2, spec->hp_independent_mode is always 0 (condition spec->hp_independent_mode_index == pinsel alwyas fails) and corresponding controls can't be activated:
/* update HP volume/swtich active state */ if (spec->codec_type == VT1708S || spec->codec_type == VT1702 || spec->codec_type == VT1718S || spec->codec_type == VT1716S || VT2002P_COMPATIBLE(spec)) { activate_ctl(codec, "Headphone Playback Volume", spec->hp_independent_mode); activate_ctl(codec, "Headphone Playback Switch", spec->hp_independent_mode); }
if the hp jack can also use "copy front" mode for "redirected headphone"
the driver don't need to disable "Headphone Playback Volume" for those 10 channels codecs or change the connection in via_independent_hp_put()
But if hp_independent_mode is always 0 because pinsel can never match hp_independent_mode_index, those controls will _never_ be activated, at least not by via_independent_hp_put, and, what's worse (as I think), once via_independent_hp_put is called they'll become inactive, even if setting the right connection for the "independent mode":
static void activate_ctl(struct hda_codec *codec, const char *name, int active) { struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name); if (ctl) { ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; ctl->vd[0].access |= active ? 0 : SNDRV_CTL_ELEM_ACCESS_INACTIVE; snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE, &ctl->id); } }
(active, as passed in by via_independent_hp_put is spec->hp_independent_mode, which is always set to 0 if spec->hp_independent_mode_index is 2, therefore the need to set hp_independent_mode more properly)
Moreover, hp_independent_mode is used by other functions, such as set_widgets_power_state_vtXXXX(), via_playback_multi_pcm_prepare(), playback_multi_pcm_prep_0(), via_playback_multi_pcm_cleanup(), therefore I think that's safer to set it properly, to avoid the risk of breaking those algorithms counting on its value.
For those 3 jacks motherobard, "channel mode" 6-8 or "Use HP as Side" switch may just need tot switch the connection to use 0x0b or 0x0c if 0b has "Side Playback Volume" and 0x0c has "Headphone Playback Volume"
By the way, if there are 3 line-outs only, I'm selecting 0x0b as multiout.hp_nid (as suggested by you), and also attaching control "Headphone Playback Volume" to it:
static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) { ... err = via_add_control(spec, VIA_CTL_WIDGET_VOL, "Headphone Playback Volume", HDA_COMPOSE_AMP_VAL(spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
2011/6/20 alex dot baldacchino dot alsasub at gmail dot com
Can your hear the same signal from black and orange jack when you playing stereo to hw:0,0,0 ?
if you look at snd_hda_multi_out_analog_prepare() in hda_codec.c,
if mout->no_share_stream=0 ,it seem that there is "upmix" feature when mout->num_dacs is 4 for those 5 jacks/6 jacks motherboard
i.e. the black and orange jacks can have the same signal as the green jack
/* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); if (!mout->no_share_stream && mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
/* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } return 0; }
I fear I cannot test it the best way (I've got a 5.1 system, but have some 'logistic' problems using it). I've made an attempt by using two headphones, connected as follows:
- one to (rear) green jack, one to orange,
- one to green, one to black,
- one to orange, one to black,
and played a short two-channels file with aplay -Dhw:0,0,0 stereo.wav a few times, in each case I was able to here (same) sound from both headsets.
However, it would seem to me that snd_hda_multi_out_analog_prepare() is not used by VIA Codecs, instead, some pcm operations are defined within patch_via.c and used by each codec, e.g.
Take a look at playback_multi_pcm_prep_0() in patch_via.c , it seem this "copy front" mode is enabled by default in via codecs
/* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] && !spec->hp_independent_mode) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
/* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); else /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); }
2011/6/20 Raymond Yau superquad.vortex2@gmail.com:
2011/6/20 alex dot baldacchino dot alsasub at gmail dot com
Take a look at playback_multi_pcm_prep_0() in patch_via.c , it seem this "copy front" mode is enabled by default in via codecs
/* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] && !spec->hp_independent_mode) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format);
/* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); else /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Yes, I had noticed it, but before seeing that line, I went out crazy thinking mout->extra_out_nid was initialized somewhere in the code (in the driver) and used in this function... Lastly, I found that place: Nowhere Land, LOL!
I must be needing some new glasses, LOL.
2011/6/8 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
By the way, should something like the above be done for capture streams as well? I've noticed (with front panel disabled) that controls "Front Mic Playback Volume" and "Front Mic Playback Switch" are correctly missing from audio-mixer widget 0x21, but node 0x29 is still 'attached' to control "Front Mic Boost Capture Volume", which is accessible through a mixer (though I didn't try to play with it; it is listed also by amixer output in above linked document). Is this the wanted/expected behaviour?
It seem that 0x2b and 0x29 does not have any mic boost capture volume, that look like "Playback Switch" when they are retasked as output for 3 jacks motherboard
Node 0x29 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Front Mic Boost Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0000233c: IN OUT HP Detect Vref caps: HIZ 50 100 Pin Default 0x02a19037: [Jack] Mic at Ext Front Conn = 1/8, Color = Pink DefAssociation = 0x3, Sequence = 0x7 Pin-ctls: 0x21: IN VREF_50 Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D3, actual=D3 Connection: 1 0x1c
Node 0x2b [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Mic Boost Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x00002334: IN OUT Detect Vref caps: HIZ 50 100 Pin Default 0x01a19036: [Jack] Mic at Ext Rear Conn = 1/8, Color = Pink DefAssociation = 0x3, Sequence = 0x6 Pin-ctls: 0x21: IN VREF_50 Unsolicited: tag=20, enabled=1 Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 2 0x0a* 0x0c
/* capture mixer elements */ static const struct snd_kcontrol_new vt1718S_capture_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x29, 0x0, - HDA_INPUT),
(I understand there must be, anyway, two
captures and two input sources, because there's still one line-in plus one (rear) mic, plus stereo-mix to deal with, and one "boost capture volume" control for the rear mic does make sense, my doubt is about its corresponding control for the now missing front mic).
The problem is in hda_verb vt1718S_volume_init_verbs
/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
node 0x21 of your vt2020 has only 5 connections
Refer to commit 4ab2d53a99b6dcee86837d2a9739bfb9f468db45
you will need to ask the author of this patch since the patch explicitly change this non exisiting connection of node 0x21 on your vt2020
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
Node 0x21 [Audio Mixer] wcaps 0x20050b: Stereo Amp-In Control: name="Front Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=3, ofs=0 Control: name="Front Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=3, ofs=0 Control: name="Rear Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Rear Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Line Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Line Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x80 0x80] [0x1f 0x1f] [0x1f 0x1f] [0x1f 0x1f] [0x97 0x97] Power states: D0 D1 D2 D3 Power: setting=D0, actual=D0 Connection: 5 0x2c 0x2b 0x2a 0x29 0x28
2011/6/8 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Adding a few printk()'s to file "patch_via.c" showed me function via_hp_build() is called before via_build_pcms() (unless front panel is disabled in BIOS, in which case via_hp_build() isn't invoked at all), therefore, when a control "Independent HP" is created, it should be 'visible' by via_build_pcms(); however, snd_hda_find_mixer_ctl(codec, "Independent HP") fails to find it until the following loop is executed inside via_build_controls:
and via_build_controls() is called after via_build_pcms(), but then it's too late (or seemed to be such) to modify the number of playback substreams. At last, I've tried the following, which worked:
The fix is to check spec->multiout.hp_nid since "Independent HP" need the extra DAC for HP when there is no HP if front panel is disabled by BIOS
static int via_build_pcms(struct hda_codec *codec) { ...
info->name = spec->stream_name_analog; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = + spec->multiout.hp_nid ? 2 : 1; info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
However there is a bug in using subdevice 1 for "Independent HP" and subdevice 0 for multi-channels
The channel count reported by snd_pcm_hw_params_get_channels_max() or snd_pcm_hw_params_test_channel() for subdevice 1 is also equal to spec->multiout.max_channels but this subdevice 1 only support stereo
2011/6/18 Raymond Yau superquad.vortex2@gmail.com:
2011/6/8 alex dot baldacchino dot alsasub at gmail dot com alex.baldacchino.alsasub@gmail.com:
Adding a few printk()'s to file "patch_via.c" showed me function via_hp_build() is called before via_build_pcms() (unless front panel is disabled in BIOS, in which case via_hp_build() isn't invoked at all), therefore, when a control "Independent HP" is created, it should be 'visible' by via_build_pcms(); however, snd_hda_find_mixer_ctl(codec, "Independent HP") fails to find it until the following loop is executed inside via_build_controls:
and via_build_controls() is called after via_build_pcms(), but then it's too late (or seemed to be such) to modify the number of playback substreams. At last, I've tried the following, which worked:
The fix is to check spec->multiout.hp_nid since "Independent HP" need the extra DAC for HP when there is no HP if front panel is disabled by BIOS
static int via_build_pcms(struct hda_codec *codec) { ...
info->name = spec->stream_name_analog; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams =
- spec->multiout.hp_nid ? 2 : 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
It might work, but might also fail, I guess. Even if everything else went ok during initialization, and multiout.hp_nid were set in vtxxxx_auto_create_hp_ctls(), via_hp_build() could fail to create an Independent HP control, because of either a failure allocating memory for it, when calling via_clone_control():
knew = via_clone_control(spec, &via_hp_mixer[0]); if (knew == NULL) return -ENOMEM;
or because the nid corresponding to the Independent HP control hasn't got enough connections:
if (spec->codec_type != VT1708) { nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); if (nums <= 1) return 0; }
As I understand it, without a control "Independent HP" with its proper .get and .put methods, that's not possible to switch between single- and multi-streaming, thus the problem is here, I think.
But perhaps, if there are not enough connections to switch from/to, it might happen that autocfg.hp_pins[0] is 0, so that:
static int vtXXXX_parse_auto_config(struct hda_codec *codec) { ...
err = vtXXX_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); ...
triggered:
static int vtXXX_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) { ...
if (!pin) return 0; ...
before spec->multiout.hp_nid is set, but it may also not happen, because, regardless of support for multi-streaming, there can be support for a front panel line-out in redirected output (refer to commit 3d83e577a8206f0f3822a3840e12f76477142ba2 and ee3c35c0827de02de414d08b2ddcbb910c2263ab, if there is need to solve that problem in via_hp_build(), it should mean that spec->multiout.hp_nid is not null in such scenarios).
However, that wouldn't solve the memory failure risk, or the risk via_hp_build is not called at all because spec->hp_mux wasn't created (though, this latter risk is fixable by moving assignment to spec->multiout.hp_nid at the end of vtXXX_auto_create_hp_ctls, and using local variables before), and anyway, in doubt, I think a safe choice is to add a proper field, I've called independent_front_panel_out, to struct via_spec, initialize it to 0 and set it to 1 in via_hp_build() after via_clone_control(spec, &via_hp_mixer[0]) succeeds, so that in via_build_pcms():
info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 1 + spec->independent_front_panel_out;
I was using it also in patch_vtXXXX() (for a few codecs, not all) to create a "Front Mic Boost Volume" control dynamically only when the front panel exist (but that's wrong, I've modified it to check for spec->autocfg.hp_pins[0], which seems to be 0 when there's no front panel seen by the BIOS).
More code is in my last mail for this thread, before this one, I've changed since then:
front_panel_out renamed independent_front_panel_out, and vt_add_front_mic_boost() now is:
static int vt_add_front_mic_boost( struct via_spec *spec, const struct snd_kcontrol_new *fmb_ctl ){ struct snd_kcontrol_new *knew;
if( spec->autocfg.hp_pins[0] ){ /* if there is a front audio panel */ knew = via_clone_control( spec, fmb_ctl ); if( knew == NULL ) return -ENOMEM; return 1; } return 0; }
(here, it would be the same to check for spec->multiout.hp_nid being set, but only if the position of the assignment to spec->multiout.hp_nid is not moved around in vtxxx_auto_create_hp_ctls)
However there is a bug in using subdevice 1 for "Independent HP" and subdevice 0 for multi-channels
The channel count reported by snd_pcm_hw_params_get_channels_max() or snd_pcm_hw_params_test_channel() for subdevice 1 is also equal to spec->multiout.max_channels but this subdevice 1 only support stereo
I haven't understood all of the pcm layer, but I guess that issue could be hard to fix without touching it at some level, or creating a separate pcm (struct snd_pcm) to handle multi-outs and hp separately, with a careful inspection of the code needed to handle them in tandem (via_playback_pcm_open() and so on).
struct hda_pcm can hold only 2 struct hda_pcm_stream elements (one actually used for playback, the other for capture):
/* for PCM creation */ struct hda_pcm { char *name; struct hda_pcm_stream stream[2]; ...
and at least snd_hda_attach_pcm() (hda_codec.c) counts on it:
static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) { struct hda_bus *bus = codec->bus; struct hda_pcm_stream *info; int stream, err;
if (snd_BUG_ON(!pcm->name)) return -EINVAL; for (stream = 0; stream < 2; stream++) { info = &pcm->stream[stream]; if (info->substreams) { err = set_pcm_default_values(codec, info); if (err < 0) return err; } } return bus->ops.attach_pcm(bus, codec, pcm); }
Moreover, only one pcm is created for a VIA codec, to handle analog outputs, plus one if there are digital connections:
(file patch_via.c)
static int via_build_pcms(struct hda_codec *codec) { struct via_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec;
codec->num_pcms = 1; codec->pcm_info = info; ....
if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms++; info++; ...
(file hda_codec.c)
int snd_hda_codec_build_pcms(struct hda_codec *codec) { unsigned int pcm; int err; ...
for (pcm = 0; pcm < codec->num_pcms; pcm++) { struct hda_pcm *cpcm = &codec->pcm_info[pcm]; int dev; ...
if (!cpcm->pcm) { dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); if (dev < 0) continue; /* no fatal error */ cpcm->device = dev; err = snd_hda_attach_pcm(codec, cpcm); ...
snd_hda_attach_pcm() calls bus->ops.attach_pcm(), that is (in file hda_intel.c) azx_attach_pcm_stream():
static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *cpcm) { struct azx *chip = bus->private_data; struct snd_pcm *pcm; struct azx_pcm *apcm; int pcm_dev = cpcm->device; int s, err; ...
err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, &pcm); ...
apcm->chip = chip; apcm->codec = codec; pcm->private_data = apcm; ...
cpcm->pcm = pcm; for (s = 0; s < 2; s++) { apcm->hinfo[s] = &cpcm->stream[s]; if (cpcm->stream[s].substreams) snd_pcm_set_ops(pcm, s, &azx_pcm_ops); } ...
again counting on two streams only:
(hda_intel.c):
struct azx_pcm { struct azx *chip; struct hda_codec *codec; struct hda_pcm_stream *hinfo[2]; };
(pcm.h):
struct snd_pcm { ... struct snd_pcm_str streams[2]; ... void *private_data; ...
struct snd_pcm_str { int stream; /* stream (direction) */ struct snd_pcm *pcm; /* -- substreams -- */ unsigned int substream_count; unsigned int substream_opened; struct snd_pcm_substream *substream; ...
struct snd_pcm_substream { struct snd_pcm *pcm; struct snd_pcm_str *pstr; void *private_data; /* copied from pcm->private_data */ ...
/* -- hardware operations -- */ struct snd_pcm_ops *ops; /* -- runtime information -- */ struct snd_pcm_runtime *runtime;
(notice above comment about field private_data, from file)
struct snd_pcm_runtime { ... /* -- hardware description -- */ struct snd_pcm_hardware hw; struct snd_pcm_hw_constraints hw_constraints; ...
struct snd_pcm_hardware { ... unsigned int channels_min; /* min channels */ unsigned int channels_max; /* max channels */ ...
(pcm.c):
int snd_pcm_new(struct snd_card *card, const char *id, int device, int playback_count, int capture_count, struct snd_pcm ** rpcm) { struct snd_pcm *pcm; int err; ...
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { ... if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) { ...
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) { int idx, err; struct snd_pcm_str *pstr = &pcm->streams[stream]; struct snd_pcm_substream *substream, *prev; ...
pstr->stream = stream; pstr->pcm = pcm; pstr->substream_count = substream_count; ... for (idx = 0, prev = NULL; idx < substream_count; idx++) { substream = kzalloc(sizeof(*substream), GFP_KERNEL); ...
substream->pcm = pcm; substream->pstr = pstr; substream->number = idx; substream->stream = stream; ....
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, struct snd_pcm_substream **rsubstream) { struct snd_pcm_str * pstr; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; ...
runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); ...
substream->runtime = runtime; substream->private_data = pcm->private_data; ... *rsubstream = substream; return 0; }
This one called by: (pcm_native.c):
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, struct snd_pcm_substream **rsubstream) { struct snd_pcm_substream *substream; int err;
err = snd_pcm_attach_substream(pcm, stream, file, &substream); ...
if ((err = substream->ops->open(substream)) < 0) goto error;
substream->hw_opened = 1; ...
*rsubstream = substream; ...
called by snd_pcm_open_file(), in turn called by snd_pcm_open(), in turn called by snd_pcm_{playback, capture}_open(), which are 'exported' as file_operations; substream->ops->open(), as set by azx_attach_pcm_stream(), is:
(hda_intel.c):
static int azx_pcm_open(struct snd_pcm_substream *substream) { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; struct azx *chip = apcm->chip; struct azx_dev *azx_dev; struct snd_pcm_runtime *runtime = substream->runtime; ...
runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_max = hinfo->channels_max; ...
In file pcm.h:
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
since substream->private_data is shared by all substreams of the same snd_pcm, in case of playback (substream->stream == SNDRV_PCM_STREAM_PLAYBACK), hinfo is spec->stream_analog_playback, and .channel_{min, max} fields hold same values for both multi-out and Independent HP subdevices (if I'm not mistaken, of course).
If my interpretation above is correct, something should change in that chain in order to have different values retrieved for different substreams of the same stream of the same pcm.
On the other hand, using separate pcms could require less invasive, yet careful, changes (affecting only patch_via.c, or one patch at a time, to test it better), but could affect any application eventually counting on analog outputs being handled by the same pcm.
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
alex dot baldacchino dot alsasub at gmail dot com
-
Raymond Yau