[alsa-devel] Tegra audio clocking
swarren at nvidia.com
Fri Jan 7 21:48:29 CET 2011
A few thoughts on re-structuring the clocking in the Tegra
audio driver. Here's what I'm thinking:
The machine driver owns configuring the root pll, pll_a, and
the cdev clock output to the codec (MCLK). The I2S driver
owns configuring the I2S clock frequency. I think all these
clocks will need to be configured in hw_params, enabled in
trigger(START/...), and disabled in trigger(STOP/...).
Does this sound sane to you? It will mean turning the clocks
on/off a lot, which goes against something you'd mentioned
above not glitching the clocks every time. However, the
following explains why:
It's not appropriate to put 100% of the clock configuration
(pll, cdev, and i2s clocks) into the I2S driver because:
* pll is shared between the 2 I2S controllers, the 1 AC'97
controller, and perhaps also SPDIF I/O in some setups.
* cdev connectivity (and hence what needs to be driven on
it) is machine-specific, and the I2S driver shouldn't know
Hence, I believe the machine driver needs to control both of
those (although using utility code to avoid cut/paste of all
the clock calls into each machine driver).
The I2S clocking shouldn't be in the machine driver itself,
because only the I2S driver knows the requirements to WAR any
issues in the Tegra I2S port. Specifically, the I2S clock
cannot be equal to srate*channels*bits, because the I2S
controller requires at least (channels*bits)+1 clocks per
sample (which ends up being channel*bits*2 in practice for
simplicity). This knowledge should really be isolated in the I2S
driver not machine level driver. Arguably though, it might not
be totally inappropriate for a utility library to encode this
knowledge, and have the machine driver call the utility library.
When the machine driver reconfigures the pll_a frequency,
that clock must have zero reference count, or the kernel will
BUG(). A 0 ref count implies that the clock is disabled, and all
child/derived clocks are disabled. In particular, the I2S clock
must be disabled. So, co-ordination is needed between the
machine and I2S drivers when reconfiguring clocks.
I can see 3 ways to co-ordinate this:
1) Have all clocks off, except between two well-defined API
calls (e.g. trigger START/STOP) such that the machine
driver has a well-defined time the clock can be
reconfigured without explicit calls to co-ordinate with the
2) Abuse the I2S driver's set_tristate function to perform
the co-ordination (or add a new snd_soc_dai_ops function for
this, or directly call the I2S driver from the machine driver).
3) Have the machine driver own the I2S clock too. See issues
Let me know if you think option 2 or 3 would actually be better
than option 1, or if there's some option I didn't think of.
More information about the Alsa-devel