Lately I've been digging into the speaker amps to see if I could resolve some of the complaints I've had with them. These chips don't seem to have any detailed information anywhere so I thought I'd document my findings here in hopes that it may be useful to others and more information might come to light.
NXP has a couple pdfs with a basic overview of the chip here: TFA9890_SDS.pdf, TFA9890A_SDS.pdf
No idea what the difference is between "TFA9890" and "TFA9890A", but the A rev PDF has some more details to it at least.
Kernel drivers for the TFA chips have been hard to find, and there's no "standard" driver.
1. Motorola seems to have written their own in-house kernel driver for it which is in the shamu kernel of course. It appears to have originated from the Moto X ("ghost") kernel, and it is by far the cleanest looking and most legible driver I've found.
2. Sony has a very ugly looking driver. They do have the registers documented the best I've seen so far though.
3. OnePlus has another odd-looking driver, this one has NXP copyright headers on it but seems to be related to the Sony one.
Problem Solving
One issue I had with the amps was how the volume cut way back when the battery voltage dropped below a certain point. I'm not talking just the gradual drop-off that happens as the battery voltage lowers over time (which is understandable), I'm talking the volume all of a sudden being halved. It turns out this is a feature of the amp:
"By limiting the supply current when the battery voltage is low, it prevents the audio system from drawing excessive load currents from the battery, which could cause a system undervoltage."
This happens by default at 3.53V. I was surprised to find that the Nexus 6 pushes the battery voltage enough for 3.53V to not only be reached, but surpassed, to as low as 3.0V. There's no way in hell the amps are powerful enough to cause a half-volt drop.
Adjusting the protection voltage level resolves this annoyance. For details, see register 0x05.
NOTE: With the Marshmallow update, the "Empty Learning Feature" of the MAX17042 battery gauge chip was enabled, and for some reason this isn't letting the battery drop to voltages as low as it previously did. So to users it may now seem like the speaker volume @ low battery issue is improved, but it's really due to what was once "35%" battery now being more like "15%".
Lately I've ran into an issue with the amps being more aggressive than they used to be with limiting the volume output. Not sure what's going on, but it started after missing an alarm for 20 minutes which was eventually interrupted by an incoming phone call. I wonder if something happened with the transition between the equalizer preset things that caused damage to the amp or speaker somehow. For the first day after this started, playing music at anywhere over 45% volume resulted in instant "volume throttling", and the more I turned it up the worse it got, eventually so bad that I couldn't hear a damn thing from the bottom speaker at all and barely heard the top one. A few days later this has greatly improved, but it's still not like it was when I got my N6.
Driver Comparison/Analysis
The Sony and OnePlus drivers disable clock gating when resetting the DSP, Moto's does not;
https://github.com/CyanogenMod/andr...c/sound/soc/codecs/tfa/src/initTfa9890.c#L107
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L289
The Sony and OnePlus drivers set some PLL registers for "optimal amplifier behavior", Moto's doesn't appear to do so;
https://github.com/CyanogenMod/andr...b4cfc/sound/soc/codecs/tfa/src/Tfa98xx.c#L273
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L617
Based on ghost's tfa9890 driver commit history, it seems like this might be taken care of with the firmware patches.
https://github.com/CyanogenMod/andr...mmit/892ac7150aba33e73837e3c713812599ba004355
https://github.com/CyanogenMod/andr...mmit/63fdeaa3c79a765f1c04f4b51c71cbb217db6707
https://github.com/CyanogenMod/andr...mmit/1ac301a19efb69f3d466fc53c6880db886409be3
https://github.com/CyanogenMod/andr...mmit/058e87a8128c233d02dff5290b23f3be0c5e86c9 (Note PLL freq/div info here)
The Sony and OnePlus drivers do some weird stuff with register 0x84 (undocumented, related to "MTP" stuff).
https://github.com/CyanogenMod/andr...fc/sound/soc/codecs/tfa/src/initTfa9890.c#L78
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L276
The OnePlus driver even tries to "recover" if 0x84 is empty. It's quite aggressive about it, you'll find it checked in numerous places.
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L812
The OnePlus driver ignores SWS and SPKS status flags in the monitor function.
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa98xx.c#L284
The main tfa98xx.c file in the OnePlus driver has some minor similarities to the Motorola driver.
Registers
0x00: Status
0x04: I2S Config
0x05: Battery Protection
-- Dropping the ProtectionThreshold (BSST) to 5 (3.23V) is more reasonable for shamu than the default of 8 (3.53V).
0x06: Audio Control
0x07: DCDC Boost
-- Moar voltage, anyone? (DCVO)
0x08: Speaker Calibration
0x09: System Control
0x0A: I2S Select
0x0C: Voltage Sense Config
Few other things that I haven't yet verified if the documentation matches up with the TFA9890:
0x41: PWM Mute Set
0x48: CurrentSense 3
0x49: CurrentSense 4
Note that the Motorola driver does mess with 0x46 through 0x49, but the values don't seem to line up with this file.
TODO
1. Try to dump and document more registers.
2. Figure out how the various eq/config/preset files work.
3. Why does fading sound all the way to one direction still seem to play through both speakers?
4. Can we speed up the channel swapping that occurs upon rotation?
NXP has a couple pdfs with a basic overview of the chip here: TFA9890_SDS.pdf, TFA9890A_SDS.pdf
No idea what the difference is between "TFA9890" and "TFA9890A", but the A rev PDF has some more details to it at least.
Kernel drivers for the TFA chips have been hard to find, and there's no "standard" driver.
1. Motorola seems to have written their own in-house kernel driver for it which is in the shamu kernel of course. It appears to have originated from the Moto X ("ghost") kernel, and it is by far the cleanest looking and most legible driver I've found.
2. Sony has a very ugly looking driver. They do have the registers documented the best I've seen so far though.
3. OnePlus has another odd-looking driver, this one has NXP copyright headers on it but seems to be related to the Sony one.
Problem Solving
One issue I had with the amps was how the volume cut way back when the battery voltage dropped below a certain point. I'm not talking just the gradual drop-off that happens as the battery voltage lowers over time (which is understandable), I'm talking the volume all of a sudden being halved. It turns out this is a feature of the amp:
"By limiting the supply current when the battery voltage is low, it prevents the audio system from drawing excessive load currents from the battery, which could cause a system undervoltage."
This happens by default at 3.53V. I was surprised to find that the Nexus 6 pushes the battery voltage enough for 3.53V to not only be reached, but surpassed, to as low as 3.0V. There's no way in hell the amps are powerful enough to cause a half-volt drop.
Adjusting the protection voltage level resolves this annoyance. For details, see register 0x05.
NOTE: With the Marshmallow update, the "Empty Learning Feature" of the MAX17042 battery gauge chip was enabled, and for some reason this isn't letting the battery drop to voltages as low as it previously did. So to users it may now seem like the speaker volume @ low battery issue is improved, but it's really due to what was once "35%" battery now being more like "15%".
Lately I've ran into an issue with the amps being more aggressive than they used to be with limiting the volume output. Not sure what's going on, but it started after missing an alarm for 20 minutes which was eventually interrupted by an incoming phone call. I wonder if something happened with the transition between the equalizer preset things that caused damage to the amp or speaker somehow. For the first day after this started, playing music at anywhere over 45% volume resulted in instant "volume throttling", and the more I turned it up the worse it got, eventually so bad that I couldn't hear a damn thing from the bottom speaker at all and barely heard the top one. A few days later this has greatly improved, but it's still not like it was when I got my N6.
Driver Comparison/Analysis
The Sony and OnePlus drivers disable clock gating when resetting the DSP, Moto's does not;
https://github.com/CyanogenMod/andr...c/sound/soc/codecs/tfa/src/initTfa9890.c#L107
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L289
The Sony and OnePlus drivers set some PLL registers for "optimal amplifier behavior", Moto's doesn't appear to do so;
https://github.com/CyanogenMod/andr...b4cfc/sound/soc/codecs/tfa/src/Tfa98xx.c#L273
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L617
Based on ghost's tfa9890 driver commit history, it seems like this might be taken care of with the firmware patches.
https://github.com/CyanogenMod/andr...mmit/892ac7150aba33e73837e3c713812599ba004355
https://github.com/CyanogenMod/andr...mmit/63fdeaa3c79a765f1c04f4b51c71cbb217db6707
https://github.com/CyanogenMod/andr...mmit/1ac301a19efb69f3d466fc53c6880db886409be3
https://github.com/CyanogenMod/andr...mmit/058e87a8128c233d02dff5290b23f3be0c5e86c9 (Note PLL freq/div info here)
The Sony and OnePlus drivers do some weird stuff with register 0x84 (undocumented, related to "MTP" stuff).
https://github.com/CyanogenMod/andr...fc/sound/soc/codecs/tfa/src/initTfa9890.c#L78
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L276
The OnePlus driver even tries to "recover" if 0x84 is empty. It's quite aggressive about it, you'll find it checked in numerous places.
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa_dsp.c#L812
The OnePlus driver ignores SWS and SPKS status flags in the monitor function.
https://github.com/OnePlusOSS/andro...5.1.1/sound/soc/codecs/tfa9890/tfa98xx.c#L284
The main tfa98xx.c file in the OnePlus driver has some minor similarities to the Motorola driver.
Registers
0x00: Status
0x04: I2S Config
0x05: Battery Protection
-- Dropping the ProtectionThreshold (BSST) to 5 (3.23V) is more reasonable for shamu than the default of 8 (3.53V).
0x06: Audio Control
0x07: DCDC Boost
-- Moar voltage, anyone? (DCVO)
0x08: Speaker Calibration
0x09: System Control
0x0A: I2S Select
0x0C: Voltage Sense Config
Few other things that I haven't yet verified if the documentation matches up with the TFA9890:
0x41: PWM Mute Set
0x48: CurrentSense 3
0x49: CurrentSense 4
Note that the Motorola driver does mess with 0x46 through 0x49, but the values don't seem to line up with this file.
TODO
1. Try to dump and document more registers.
2. Figure out how the various eq/config/preset files work.
3. Why does fading sound all the way to one direction still seem to play through both speakers?
4. Can we speed up the channel swapping that occurs upon rotation?