Subject: [patch] snapper(4) issues
To: None <port-macppc@netbsd.org>
From: Marco Trillo <marcotrillo@gmail.com>
List: port-macppc
Date: 10/07/2007 13:36:10
------=_Part_33963_2422048.1191764170982
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi,

The attached patch fixes a couple of issues with the snapper(4) driver:

 o In the bass, treble and gain controls, center the 0 dB point at the
value 128. This is to make them easier to configure and set up
correctly: the 128 value is the neutral value (so bass/treble/gain is
disabled -- which is what is desired in many cases). Values higher
than 128 emphasize bass/treble or add gain; values lesser than 128
deemphasize bass/treble or add negative gain. Also make 128 the
default value.

 o The TAS3004 seems to have a hardware fault which causes it to delay
the left channel by one sample, causing phase differences between
channels. This is explained in the Apple code, as shown in this quote
from the AppleTAS3004Audio.cpp file:

// [...] fixing the phase relationship between the
// left and right channels where a hardware fault in the TAS3004 results in
// a one sample delay of the left channel [...]

This issue can be compensated by delaying the right channel by one
sample. The attached patch implements this using a simple filter.
This is a equivalent solution to what Apple does in:

<http://www.opensource.apple.com/darwinsource/10.4.9.ppc/AppleOnboardAudio-256.2.5/AppleLegacyAudio/AppleDBDMAAudio/Apple02DBDMAAudioClip.c>
(function delayRightChannel(), note that in the Apple code there are
two TAS3004 drivers, and one of them implements another solution which
involves programming the TAS3004 biquad filters to delay the right
channel, but this seems more difficult to get right)

This problem does not affect the TAS3001.

 o The TAS3001 bass table is different from the table used in the code
(which corresponds roughly to TAS3004 bass/treble and TAS3001 treble),
so bass values are set up incorrectly. And there is a lot of error,
for example, 0 dB is 0x3E in this table while 0x72 in the other table.
Fix this issue using simple method (which at least gets 0 dB right).

Apart from that, the patch also contains the following general cleanup:

 o Don't hardcode absolute addresses for the FCR registers. Use the
"baseaddr" parameter passed from obio(4).

 o Use dbdma_alloc() to alloc the command buffers instead of doing the
alignment manually. Don't hardcode the "max pages" value.

 o The "sc_swvol" and "sc_flags" members are redundant: use a single
mode member.

 o Some mixer parameters should be disabled if a "software codec" is used.

 o Be a bit more verbose and print if the codec is TAS3001 or TAS3004
(not only if there is a software codec).

 o The mixer members of snapper_softc can be u_char, not u_int, since
they are 0-255 values.

 o Use TAILQ_FOREACH() and device_is_a() where appropiate [instead of
a manual loop and strncmp()].

I hope that this is useful!

Thanks,
Marco

------=_Part_33963_2422048.1191764170982
Content-Type: application/x-gzip; name="snapper.c.diff.gz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz"; filename="snapper.c.diff.gz";
 filename="snapper.c.diff.gz"

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
------=_Part_33963_2422048.1191764170982--