[alsa-devel] HP-path handling on VIA codecs

Takashi Iwai tiwai at suse.de
Mon Jul 11 10:53:30 CEST 2011

At Sun, 10 Jul 2011 16:55:45 +0200,
alex dot baldacchino dot alsasub at gmail dot com wrote:
> 2011/7/8 Takashi Iwai <tiwai at suse.de>:
> > Hi,
> >
> > while testing with the gathered alsa-info.sh outputs, now I'm
> > considering how to improve the handling of the headphone (and speaker)
> > output paths.
> >
> > On VIA codecs, it looks like that the loopback mixer always contains
> > the input from the front DAC, and the front DAC is the only DAC that
> > can be mixed with loopback.  (It might be not always, but on many
> > codecs, at least).
> >
> > I mean, some codecs of other vendors have a connection like:
> >   Input-pin(s) -> Mix1 -> Mix2 -> Output1
> >   DAC1                 -> Mix2 -> Output1
> >   Input-pin(s) -> Mix3 -> Mix4 -> Output2
> >   DAC2                 -> Mix4 -> Output2
> >   ....
> > For such devices, you can use DAC as the volume control of each output
> > channel (HP, line-out, speaker, etc).  So I started implementing in
> > that way for VIA, too.  It's found as two parsed output paths,
> > spec->hp_out, and spec->hp_dep_out,
> >
> > But later I found that VIA has only
> >   Input-pin(s) -> Mix1 -> Output1
> >   DAC1         -> Mix1 -> Output1
> >        or
> >   DAC1                 -> Output1
> >
> >   Input-pin(s) -> Mix1 -> Output1
> >   DAC1         -> Mix1 -> Output2
> >       or
> >   DAC2                 -> Output2
> >   ...
> >
> > Suppose the output2 is HP, it means that you can't have an individual
> > volume control via DAC2 if you want to mix the loopback.
> > Now we face a dilemma: usually an individual volume control is really
> > nice.  But, if we take the individual control, it looses the loopback,
> > as these are mutual-exclusive for HP (or speaker) outputs.
> >
> > Thus we need to decide a policy: either
> >
> > A. HP has no volume unless independent mode
> >
> > B. Don't mix loopback to HP or others (but front-out)
> >
> > C. Allow to turn on/off aa-loopback mode; when loopback is enabled,
> >   switch the path to hp_dep without volume control (only for front).
> >   When loopback is disabled, switch to the direct DAC path.
> >
> > A is the old driver behavior, I guess.  B is somewhat similar to now.
> > C would be smart, but need more implementation and add yet another
> > mixer element.
> >
> > What do you think?
> >
> >
> > thanks,
> >
> > Takashi
> >
> Personally, if I'm not misunderstanding it, I'd vote for C. I had
> tried something similar for old implementation, and can tell it worked
> and was easy enough to implement, AFAICT (I can resend the code if
> found of any interest, since it seems to me my first mail about it
> went lost, at least that's not in this mailing list archives, though
> that's based on the old code, and could be useful only to exchange
> ideas).

A patch will be always useful, even for the older code.

Regarding ML archive: are you subscribed to ML?  alsa-devel ML is
basically only for subscribers, and posts from non-subscribers are
postponed, manually approved.  Sometimes the approval work delayed and
the posts are canceled.

But, currently alsa-devel ML seems stopped by some reason, so it's
anyway useless :)

> It was quite simple: I used a few new fields in struct via_spec and
> two input mux controls, one for hp and one for front (to have a fine
> grained control and disable/enable aa path independently for those
> lines - and test if it could work this way), called "Direct Output"
> and "HP Direct Output" (I chose names thinking about the sound coming
> straight from analog inputs and going to analog outputs through the AA
> mixer, but could be, for instance, "({Front, HP}) Output Mode" (or
> "Output Source") with items labeled "Mixed with input" (or "Stereo
> mixer") and "Playback only", or the like). Corresponding controls
> callbacks worked on the mixer connected to each output jack and
> getting input from a dac (through an audio selector) and from the aa
> mixer,  choosing the right mixer basing on the control they were
> invoked for, and the corresponding values in via_spec new fields:
> .get() returned the (negated) value of the mute bit of aa mixer
> connection in the chosen mixer connection list, and .put()
> muted/un-muted such a connection if in a different state (a better
> behavior would be to alternatively mute/unmute the connection to the
> dac and the connection to the loopback mixer, taking care of hp state
> (working on aa mixer connection only for hp mixer while in independent
> mode), and, of course, there could be a single switch/mux control to
> enable/disable the aa path globally).
> My reason to test such a solution was some noise I constantly got (and
> still get with newer code, but for Independent HP in latest version)
> from my headset microphone to each such line out (front and hp), but I
> can think, for instance, of someone wishing to listen to something
> while recording something else from line-in and not aiming to mix both
> sounds in output.

Yes, I think there are both type of users, too.

> But I guess some problems could arise in actual implementation, unless
> I'm overvaluing/misunderstanding them.
> First of all, now there's a pair of PCM Playback controls (switch and
> volume) attached to aa mixer and I'm not sure if muting connections to
> it could affect those controls (specially the volume). In such a case,
> they could be moved to the front dac, but this problem, if existing,
> could be re-raised for hp path in independent mode (in which case
> front dac and attached controls would be out of the game). An
> alternative could be leaving those controls where they're now, but
> reimplementing callbacks so that they could use a different nid (and
> work on more than one nid at a time). This way:
> - the .put callback for turning aa-loopback on/off for a certain nid
> (or all affected nids at once, if only one such control existed) would
> be responsible: 1. to record somewhere (accessible by via_spec) the
> nid(s) to work on (quite easy with separate controls attached to each
> affected mixer: the nid to gather would be just the actual one being
> unmuted in the two-entries connection list of passed-in kcontrol nid
> or the non loopback connection for hp mixer in independent mode), 2.
> to set the right volume (not just un-muting) for the non-loopback
> path(s) when switching to it (basing on pcm volume setting) and
> muting/unmuting the connection(s) to aa mixer as needed;
> - the .put callback for adjusting pcm volume setting would work as now
> for aa mixer nid (both to let it work as expected when used as source
> for output and to gather correct values from it, but also for correct
> handling of capture from stereo mixer), while performing same
> operations for each alternative nid, gathered from a proper list and
> being non-null and different from aa mixer nid;
> - the .get callback for "PCM Playback Volume" could be left untouched
> (to always gather infos from the 'base' nid the control is attacthed
> to).
> Similar considerations could/should be done for the pcm switch, that
> (now, in my case) has the effect to mute/unmute front output (only).
> However, I might be missing the point since I'm not sure how those
> controls are expected to work properly. Previously, with old code, I
> had no PCM Playback Switch and a "standalone" PCM Playback Volume,
> detached from any nid, and such seemed to work for all outputs, as far
> as I remember (I should re-install old implementation to make a test);
> alsa-info.sh reported following output for alsactl:
> 	control.31 {
> 		iface MIXER
> 		name 'PCM Playback Volume'
> 		value.0 255
> 		value.1 255
> 		comment {
> 			access 'read write user'
> 			type INTEGER
> 			count 2
> 			range '0 - 255'
> 			tlv '0000000100000008ffffec1400000014'
> 			dbmin -5100
> 			dbmax 0
> 			dbvalue.0 0
> 			dbvalue.1 0
> 		}
> 	}
> Now I have both controls attached to 0x21, they seem to have effect on
> front path only (throughout aa mixer - previously its connection to
> front dac, for my codec, was just un-muted with an initialization
> verb) and alsa-info.sh reports:
> 	control.9 {
> 		iface MIXER
> 		name 'PCM Playback Volume'
> 		value.0 22
> 		value.1 22
> 		comment {
> 			access 'read write'
> 			type INTEGER
> 			count 2
> 			range '0 - 31'
> 			dbmin -3450
> 			dbmax 1200
> 			dbvalue.0 -150
> 			dbvalue.1 -150
> 		}
> 	}
> 	control.10 {
> 		iface MIXER
> 		name 'PCM Playback Switch'
> 		value.0 true
> 		value.1 true
> 		comment {
> 			access 'read write'
> 			type BOOLEAN
> 			count 2
> 		}
> 	}
> Similar concerns could be raised for Master Playback controls, given
> some codecs (but not mine - vt2020) holds them via their aa mixer nid.

Indeed how to name the control element in such a case is a difficult
problem.  Since the role of the mixer element changes depending on the
mode, it can't be simply named.  The current naming with "PCM" is
actually confusing.

Once when we implement the loopback mode-switch, I'd name it like
"Loopback PCM" or such, to make clear that it belongs only to a
loopback path.

> Another, possibly minor, problem, as pointed out in Lydia's answer,
> could be the somewhat inconsistence introduced between newer codecs
> supporting solution C and older ones unable to mute their aa mixer
> without loosing their front dac (because their aa mixer is just
> between their front dac and their rear green jack, but also between
> front dac and hp jack when in redirected mode). Such could be simply
> disregarded, taken as a consequence of a different set of supported
> features; therefore, it should be possible to choose automatically
> whether to create the proper control(s) for turning on/off aa-loopback
> or not while parsing output paths, looking at the connection lists of
> nids in a certain path, starting from an output jack and moving
> towards a dac, and looking if an element (a mixer or the jack nid
> itself) is found with at least two connections, one of which should be
> the aa mixer nid and the other one either the front dac nid, or an
> audio selector connected to it. For hp path the non-loopback
> connection shouldn't be hp dac directly (not passing through a
> selector), or the implementation would conflict with redirected output
> if such a dac were shared, which is the case for several codecs,
> specially older ones (newer ones seem to use an audio selector,
> instead, for front and hp), though I'm not sure if that's the same for
> all such codecs - hp_indep_shared could tell that, so that a few older
> codecs could support solution C for hp only, but in such a case
> solution C would behave mostly as B in current implementation, but for
> redirected mode, given front stream would be 'cloned' for hp dac if
> not shared, so hp could get loopback mixed in or not at whim, even if
> such would be inconsistent with front being always mixed with
> loopback).

Yeah, more small glitches may come out.  Let's see step by step :)



More information about the Alsa-devel mailing list