[alsa-devel] [PATCH 1/4] ASoC: TLV320AIC23B Support more sample rates
Takashi Iwai
tiwai at suse.de
Wed Nov 5 21:35:01 CET 2008
At Wed, 5 Nov 2008 18:53:28 +0000,
Mark Brown wrote:
>
> From: Troy Kisky <troy.kisky at boundarydevices.com>
>
> Add support for more sample rates, different crystals
> and split playback/capture rates.
>
> Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
> Acked-by: Arun KS <arunks at mistralsolutions.com>
> Signed-off-by: Mark Brown <broonie at opensource.wolfsonmicro.com>
> ---
> sound/soc/codecs/tlv320aic23.c | 227 ++++++++++++++++++++++++++++++++--------
> 1 files changed, 182 insertions(+), 45 deletions(-)
>
> diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
> index 44308da..c1b2060 100644
> --- a/sound/soc/codecs/tlv320aic23.c
> +++ b/sound/soc/codecs/tlv320aic23.c
> +unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
> + int dac, int dac_l, int dac_h, int need_dac)
Should be static.
> +{
> + if ((adc >= adc_l) && (adc <= adc_h) &&
> + (dac >= dac_l) && (dac <= dac_h)) {
> + unsigned diff_adc = need_adc - adc;
> + unsigned diff_dac = need_dac - dac;
> + unsigned score;
> + if (((int)diff_adc) < 0)
> + diff_adc = -diff_adc;
> + if (((int)diff_dac) < 0)
> + diff_dac = -diff_dac;
> + score = diff_adc + diff_dac;
> + return score;
> + }
> + return 0xffffffff;
-1 would be simpler and safer (for possible missing f's).
> +}
> +int find_rate(int mclk, u32 need_adc, u32 need_dac)
Use static.
> +{
> + int i, j;
> + int best_i = -1;
> + int best_j = -1;
> + int best_div = 0;
> + unsigned best_score = 0xffffffff;
-1 would be safer.
> + int adc_l, adc_h, dac_l, dac_h;
> +
> + need_adc *= SR_MULT;
> + need_dac *= SR_MULT;
> + /*
> + * rates given are +/- 1/32
> + */
> + adc_l = need_adc - (need_adc >> 5);
> + adc_h = need_adc + (need_adc >> 5);
> + dac_l = need_dac - (need_dac >> 5);
> + dac_h = need_dac + (need_dac >> 5);
> + for (i = 0; i < 4; i++) {
> + int base = mclk / bosr_usb_divisor_table[i];
> + int mask = sr_valid_mask[i];
> + for (j = 0; j < 16; j++, mask >>= 1) {
> + int adc;
> + int dac;
> + int score;
> + if ((mask & 1) == 0)
> + continue;
> + adc = base * sr_adc_mult_table[j];
> + dac = base * sr_dac_mult_table[j];
> + score = get_score(adc, adc_l, adc_h, need_adc,
> + dac, dac_l, dac_h, need_dac);
> + if (best_score > score) {
> + best_score = score;
> + best_i = i;
> + best_j = j;
> + best_div = 0;
> + }
> + score = get_score((adc >> 1), adc_l, adc_h, need_adc,
> + (dac >> 1), dac_l, dac_h, need_dac);
> + /* prefer to have a /2 */
> + if ((score != 0xffffffff) && (best_score >= score)) {
> + best_score = score;
> + best_i = i;
> + best_j = j;
> + best_div = 1;
> + }
> + }
> + }
> + return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
> +}
> +
> +static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
> + u32 *sample_rate_adc, u32 *sample_rate_dac)
> +{
> + int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
> + int sr = (src >> 2) & 0x0f;
> + int val = (mclk / bosr_usb_divisor_table[src & 3]);
> + int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
> + int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
> + if (src & TLV320AIC23_CLKIN_HALF) {
> + adc >>= 1;
> + dac >>= 1;
> + }
> + *sample_rate_adc = adc;
> + *sample_rate_dac = dac;
> +}
> +
> +static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
> + u32 sample_rate_adc, u32 sample_rate_dac)
> +{
> + /* Search for the right sample rate */
> + int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
> + if (data < 0) {
> + printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
> + __func__, sample_rate_adc, sample_rate_dac);
> + return -EINVAL;
> + }
> + tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
> + if (1) {
For what?
Takashi
More information about the Alsa-devel
mailing list