[Nexus 5 Themes and Apps] chdloc:
I played with mixer_paths.xml some more and now I have a gain setup that seems to work for me, both in terms of keeping distortions at bay and in terms of left-right speaker balance.

My "speaker" device now looks like this:

<path name="speaker">

<ctl name="SLIM RX1 MUX" value="AIF1_PB" />

<ctl name="SLIM RX2 MUX" value="AIF1_PB" />

<ctl name="SLIM_0_RX Channels" value="Two" />

<ctl name="RX1 MIX1 INP1" value="RX1" />

<ctl name="RX7 MIX1 INP2" value="RX2" />

<ctl name="RX1 Digital Volume" value="89" />

<ctl name="RX7 Digital Volume" value="81" />

<ctl name="SPK DRV Volume" value="6" />

<ctl name="CLASS_H_DSM MUX" value="DSM_HPHL_RX1" />

<ctl name="DAC1 Switch" value="1" />

</path>

Note that I deleted a few entries that are unnecessary along with the two cross-mixing entries mentioned earlier. Also, in my case, the gain difference between the main speaker (81) and the handset speaker (89) is eight ticks, which I believe corresponds to 8 dB. It is important to note that both the absolute and relative levels between the two loudspeakers are, in general, device-specific due to loudspeaker tolerances. You can certainly start with my values and optimize for your device.

In order to make optimization easier, I attached the command-line program "tinymix" which is part of AOSP, but is not installed by default.

Uncompress the binary, copy it somewhere to your binary search path such as /system/bin , and adjust the permissions to 744.

With this binary, you can use the shell to adjust the gain values on-the-fly while you are listening to audio, e.g. as root

# tinymix "RX1 Digital Volume" A

# tinymix "RX7 Digital Volume" B

where A,B ={0,124} is the desired gain level. Keep in mind that the values will always reset to the ones sitting in mixer_paths.xml as soon as you play with the playback controls of your media player, i.e. pause/resume, start/stop, and skip. For the values to "stick" you will have to modify mixer_paths.xml directly followed by a reboot. I would advise against cranking up the earpiece loudspeaker gain value to something higher than the lower 90s as distortions will be very audible at high playback volumes. Even though the audio codec used (WCD9320) seems to be having a current limiter in the earpiece path, damage to the loudspeaker cannot be ruled out if the loudspeaker is heavily distorting for a long period of time.

In order to shut the handset speaker off during a (cellular and maybe VoIP) handsfree call, I modified another device in mixer_paths.xml, i.e.

<path name="voice-speaker">

<path name="speaker" />

<ctl name="SPK DRV Volume" value="8" />

<ctl name="RX7 Digital Volume" value="94" />

<ctl name="RX1 Digital Volume" value="0" />

</path>

which simply sets the handset speaker gain to zero. Keeping the handset speaker on during a cellular speakerphone call may cause the phone's echo control to "work harder" than necessary and maybe even fail in some instances.

Caveat: The earpiece loudspeaker does not seem to be turning off when using the speakerphone on voice-capable apps other than cellular telephony, such as Google Hangouts (via Dialer), Skype, Bria, etc, as these apps seem to be calling the "speaker" device directly (which of course now turns both loudspeakers on by default). This may wreck havoc on echo control. As I'm not really using any of these services on speakerphone on a regular basis, this is not a real problem for me. The only way around this issue that I can see right now is (other than lowering the playback volume as much as possible or seriously messing with the audio HAL) to use a service like Tasker to execute

tinymix "RX1 Digital Volume" 0

whenever speakerphone mode is detected, which is non-trivial but possible.

Edit (12/16/2014): I made some "frequency response" measurements of the two loudspeakers. I held my sound level meter at about 30 cm distance from the phone, approximately centered between the two loudspeakers. As can be seen from the attached plot, the two loudspeakers match pretty well in the perceptually important frequency range of 1 kHz and 4 kHz. The discrepancy between the two loudspeakers at frequencies higher than around 4.5 kHz can be explained by the fact that the main loudspeaker is not front-facing and high frequencies get attenuated more as a result of its placement with respect to the listener.