On Tue, Jan 26, 2010 at 02:04:45PM +0100, Guennadi Liakhovetski wrote:
This is mostly good, there's a few relatively small changes needed but the broad concept is fine:
wm8978 needs an input clock for its operation, and it needs to know its frequency. The only way to supply this information to the driver is to use
snd_soc_dai_set_pll(dai, 0, 0, f_in, f_out);
where if f_in == 0, input clock is off and the driver has nothing better to do but to switch its own clocking off too. f_out is the frequency, that the user (board) is asking wm8978 to provide on its OPCLK (GPIO1) output. If f_out == 0, this means, the board does not need that output _and_ it is asking the codec to switch PLL off. Otherwise PLL is immediately configured and switched on.
The PLL is not tied in with OPCLK. set_pll() should pay no attention to OPCLK, it should just start the PLL when given a configuration and stop the PLL when given no input/output frequency.
Remember, OPCLK may not be being used at all and there are separate dividers from the PLL output for it and the main SYSCLK in the CODEC.
- having configured codec's PLL the board can select, which clock the codec shall be using as a source for its system clock - PLL or codec input clock directly. The board uses
snd_soc_dai_set_sysclk(dai, WM8978_PLL, f_sysclk, 0);
or
snd_soc_dai_set_sysclk(dai, WM8978_MCLK, f_sysclk, 0);
This is mostly OK but...
for this. Notice, that f_sysclk is ignored, because in wm8978 it is fixed at 256 * fs, and therefore it has to be configured in .hw_params().
If the MCLK is being used as SYSCLK then the frequency should be used - if it's recorded then the driver can automatically configure MCLKDIV to generate the 256fs by itself (see below). It could also generate constraints for ALSA to let applications know what frequencies are supported, though that's less urgent.
The clock rate passed in needn't be the actual system clock, it's more useful if it's the rate of the clock that is used to generate that, which is what the outside world can see.
- in .hw_params() we configure the MCLK divider, based on the system clock frequency and baudrate, and set up the selected clock source.
This allows for the most flexible clock configuration, one can even configure to use PLL for output clock and input clock directly for the system clock, even if such a configuration doesn't make much sense.
This is why you need the input clock frequency when the MCLK is being used directly - you can't configure the divider without knowing what MCLK is.